Erlang与C构建的节点通讯
2014-11-06 00:25
176 查看
Erlang节点之间的通讯,主要用于两个Erlang节点之间的通讯,但Erlang还支持与java构建的节点通讯,甚至与c构建的节点通讯,前面两种方式在我以前的文章都有讲到,所以这里讲Erlang与c构建的节点通讯。
Cnode与erl_interface
想用C构建一个erlang节点,要利用Erlang的erl_interface接口来实现。c建立的节点,叫CNode ,其中,erl_interface除了实现一些基本的节点连接,消息发送接收,还实现Erlang Term 的构建解析。
CNode是除了nif之外的另一种c扩展erlang方式,但对比nif来说这种方式不会引起erlang的crash,因为他们在不同的进程上,底层通过socket通讯。
另外一个问题,CNode在erlang集群中节点是隐藏的,所以在erlang中用nodes()无法找到CNode,但节点连接成功后可以通过nodes(connected)获取到。
CNode与Erlang通讯
下面讲述如何在Windows下使用CNode与Erlang通讯(demo下载)
一、前期准备
1、下载erlang二进制安装包,这里以R16B02为例。
2、安装erlang后,到安装目录取erlang头文件和静态库包:
erl头文件:erl5.10.3\lib\erl_interface-3.7.14\include\
erl静态库:erl5.10.3\lib\erl_interface-3.7.14\lib,静态库这里只用到ei_md.lib和erl_interface_md.lib
二、新建c项目
1、新建一个空项目,命名为cnode
2、把include文件夹和lib文件夹复制到工程目录下
3、修改项目属性,字符集选使用 Unicode 字符集
4、修改项目属性,VC++ 目录的包含目录添加“include”,库添加“lib”
5、工程新增文件cnode.c,保存以下代码:
#include <stdio.h>
#include <sys/types.h>
#ifdef _WIN32
# define __WIN32__
# include <WinSock2.h>
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "ei_md.lib")
# pragma comment(lib, "erl_interface_md.lib")
# pragma comment(linker, "/NODEFAULTLIB:MSVCRTD.LIB")
#endif
#include "erl_interface.h"
#include "ei.h"
#define BUFSIZE 1000
#define PORT 8088
int foo(int x) {
return x+1;
}
int bar(int y) {
return y*2;
}
int main(int argc, char **argv) {
struct in_addr addr; /* 32-bit IP number of host */
int port; /* Listen port number */
int listen; /* Listen socket */
int fd; /* fd to Erlang node */
ErlConnect conn; /* Connection data */
int loop = 1; /* Loop flag */
int got; /* Result of receive */
unsigned char buf[BUFSIZE]; /* Buffer for incoming message */
ErlMessage emsg; /* Incoming message */
ETERM *fromp, *tuplep, *fnp, *argp, *resp;
int res;
#ifdef _WIN32
//初始化winsock服务
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
#endif
port = PORT;
erl_init(NULL, 0);
addr.s_addr = inet_addr("127.0.0.1");
if (erl_connect_xinit("idril", "cnode", "cnode@127.0.0.1",
&addr, "secretcookie", 0) == -1)
erl_err_quit("erl_connect_xinit");
/* Make a listen socket */
if ((listen = my_listen(port)) <= 0)
erl_err_quit("my_listen");
if (erl_publish(port) == -1)
erl_err_quit("erl_publish");
if ((fd = erl_accept(listen, &conn)) == ERL_ERROR)
erl_err_quit("erl_accept");
fprintf(stderr, "Connected to %s\n\r", conn.nodename);
while (loop) {
got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);
if (got == ERL_TICK) {
/* ignore */
} else if (got == ERL_ERROR) {
loop = 0;
} else {
if (emsg.type == ERL_REG_SEND) {
fromp = erl_element(2, emsg.msg);
tuplep = erl_element(3, emsg.msg);
fnp = erl_element(1, tuplep);
argp = erl_element(2, tuplep);
if (strncmp(ERL_ATOM_PTR(fnp), "foo", 3) == 0) {
res = foo(ERL_INT_VALUE(argp));
} else if (strncmp(ERL_ATOM_PTR(fnp), "bar", 3) == 0) {
res = bar(ERL_INT_VALUE(argp));
}
resp = erl_format("{cnode, ~i}", res);
erl_send(fd, fromp, resp);
erl_free_term(emsg.from); erl_free_term(emsg.msg);
erl_free_term(fromp); erl_free_term(tuplep);
erl_free_term(fnp); erl_free_term(argp);
erl_free_term(resp);
}
}
}
}
int my_listen(int port) {
int listen_fd;
struct sockaddr_in addr;
int on = 1;
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (-1);
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
memset((void*) &addr, 0, (size_t) sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
return (-1);
listen(listen_fd, 5);
return listen_fd;
}编译项目后,会生成cnode.exe的程序。这里要先启动erlang epmd服务,再跑这个程序。原因是erlang节点之间的通讯要依赖一个底层的端口映射服务epmd,这个模块的主要功能是提供通过相互通过name来识别机器的机制。
7、启动erlang epmd服务
可以先在本机启动一个erlang节点,erlang会自动起这个epmd服务。demo中也带了这个程序epmd.exe,手动执行即可
8、运行erlang节点
C:\>erl -name e1@127.0.0.1 -setcookie secretcookie
Eshell V5.10.3 (abort with ^G)
(e1@127.0.0.1)1> net_kernel:connect('cnode@127.0.0.1').
true
(e1@127.0.0.1)2> {any, 'cnode@127.0.0.1'} ! {call, self(), {bar, 3}}.
{call,<0.36.0>,{bar,3}}
(e1@127.0.0.1)3> flush().
Shell got {cnode,6}
ok
(e1@127.0.0.1)4> {any, 'cnode@127.0.0.1'} ! {call, self(), {foo, 3}}.
{call,<0.36.0>,{foo,3}}
(e1@127.0.0.1)5> flush().
Shell got {cnode,4}
ok完整demo下载:http://download.csdn.net/detail/cwqcwk1/8126053
demo无法编译或无法起来的原因?
之前写过nif的例子,有网友表示demo无法跑起来,这里总结其中的情况:
1、demo的erlang版本是R16B02,必须使用这个版本的erlang,否则会有问题。下载页
2、我的编译器是vs2010,必须安装有vs2010以上的编译器。如果没有安装,只是想运行这个demo需要安装vc2010运行库
3、epmd服务未启动,demo中自带了epmd.exe,双击即可。或者先在本机启动一个erlang节点,erlang会自动起这个服务。‘
4、其他erlang节点之间无法通讯的原因,还有cookie、名字问题,参考这篇文章
上面讲的是CNode做服务端节点的例子,下面也贴下CNode做客户端节点的代码:int main(int argc, char **argv) {
int fd; /* fd to Erlang node */
int loop = 1; /* Loop flag */
int got; /* Result of receive */
unsigned char buf[BUFSIZE]; /* Buffer for incoming message */
ErlMessage emsg; /* Incoming message */
ETERM *fromp, *tuplep, *fnp, *argp, *resp;
int res;
erl_init(NULL, 0);
if (erl_connect_init(1, "secretcookie", 0) == -1)
erl_err_quit("erl_connect_init");
if ((fd = erl_connect("e1@idril")) < 0)
erl_err_quit("erl_connect");
fprintf(stderr, "Connected to ei@idril\n\r");
while (loop) {
got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);
if (got == ERL_TICK) {
/* ignore */
} else if (got == ERL_ERROR) {
loop = 0;
} else {
if (emsg.type == ERL_REG_SEND) {
fromp = erl_element(2, emsg.msg);
tuplep = erl_element(3, emsg.msg);
fnp = erl_element(1, tuplep);
argp = erl_element(2, tuplep);
if (strncmp(ERL_ATOM_PTR(fnp), "foo", 3) == 0) {
res = foo(ERL_INT_VALUE(argp));
} else if (strncmp(ERL_ATOM_PTR(fnp), "bar", 3) == 0) {
res = bar(ERL_INT_VALUE(argp));
}
resp = erl_format("{cnode, ~i}", res);
erl_send(fd, fromp, resp);
erl_free_term(emsg.from); erl_free_term(emsg.msg);
erl_free_term(fromp); erl_free_term(tuplep);
erl_free_term(fnp); erl_free_term(argp);
erl_free_term(resp);
}
}
}
}代码就参照上面的方法编译了
最后,如果对erlang有什么问题或者对某些技术感兴趣的,都可以回帖告诉我。我看到就会找时间研究一下,做一个分享或讨论。
扩展阅读:
erlang与java构建的节点通讯
erlang节点通讯例子及问题分析
erlang在windows下和虚拟机节点通信
Windows下使用NIF扩展Erlang方法
参考:http://blog.csdn.net/mycwq/article/details/40836273 http://www.erlang.org/doc/tutorial/cnode.html
Cnode与erl_interface
想用C构建一个erlang节点,要利用Erlang的erl_interface接口来实现。c建立的节点,叫CNode ,其中,erl_interface除了实现一些基本的节点连接,消息发送接收,还实现Erlang Term 的构建解析。
CNode是除了nif之外的另一种c扩展erlang方式,但对比nif来说这种方式不会引起erlang的crash,因为他们在不同的进程上,底层通过socket通讯。
另外一个问题,CNode在erlang集群中节点是隐藏的,所以在erlang中用nodes()无法找到CNode,但节点连接成功后可以通过nodes(connected)获取到。
CNode与Erlang通讯
下面讲述如何在Windows下使用CNode与Erlang通讯(demo下载)
一、前期准备
1、下载erlang二进制安装包,这里以R16B02为例。
2、安装erlang后,到安装目录取erlang头文件和静态库包:
erl头文件:erl5.10.3\lib\erl_interface-3.7.14\include\
erl静态库:erl5.10.3\lib\erl_interface-3.7.14\lib,静态库这里只用到ei_md.lib和erl_interface_md.lib
二、新建c项目
1、新建一个空项目,命名为cnode
2、把include文件夹和lib文件夹复制到工程目录下
3、修改项目属性,字符集选使用 Unicode 字符集
4、修改项目属性,VC++ 目录的包含目录添加“include”,库添加“lib”
5、工程新增文件cnode.c,保存以下代码:
#include <stdio.h>
#include <sys/types.h>
#ifdef _WIN32
# define __WIN32__
# include <WinSock2.h>
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "ei_md.lib")
# pragma comment(lib, "erl_interface_md.lib")
# pragma comment(linker, "/NODEFAULTLIB:MSVCRTD.LIB")
#endif
#include "erl_interface.h"
#include "ei.h"
#define BUFSIZE 1000
#define PORT 8088
int foo(int x) {
return x+1;
}
int bar(int y) {
return y*2;
}
int main(int argc, char **argv) {
struct in_addr addr; /* 32-bit IP number of host */
int port; /* Listen port number */
int listen; /* Listen socket */
int fd; /* fd to Erlang node */
ErlConnect conn; /* Connection data */
int loop = 1; /* Loop flag */
int got; /* Result of receive */
unsigned char buf[BUFSIZE]; /* Buffer for incoming message */
ErlMessage emsg; /* Incoming message */
ETERM *fromp, *tuplep, *fnp, *argp, *resp;
int res;
#ifdef _WIN32
//初始化winsock服务
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
#endif
port = PORT;
erl_init(NULL, 0);
addr.s_addr = inet_addr("127.0.0.1");
if (erl_connect_xinit("idril", "cnode", "cnode@127.0.0.1",
&addr, "secretcookie", 0) == -1)
erl_err_quit("erl_connect_xinit");
/* Make a listen socket */
if ((listen = my_listen(port)) <= 0)
erl_err_quit("my_listen");
if (erl_publish(port) == -1)
erl_err_quit("erl_publish");
if ((fd = erl_accept(listen, &conn)) == ERL_ERROR)
erl_err_quit("erl_accept");
fprintf(stderr, "Connected to %s\n\r", conn.nodename);
while (loop) {
got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);
if (got == ERL_TICK) {
/* ignore */
} else if (got == ERL_ERROR) {
loop = 0;
} else {
if (emsg.type == ERL_REG_SEND) {
fromp = erl_element(2, emsg.msg);
tuplep = erl_element(3, emsg.msg);
fnp = erl_element(1, tuplep);
argp = erl_element(2, tuplep);
if (strncmp(ERL_ATOM_PTR(fnp), "foo", 3) == 0) {
res = foo(ERL_INT_VALUE(argp));
} else if (strncmp(ERL_ATOM_PTR(fnp), "bar", 3) == 0) {
res = bar(ERL_INT_VALUE(argp));
}
resp = erl_format("{cnode, ~i}", res);
erl_send(fd, fromp, resp);
erl_free_term(emsg.from); erl_free_term(emsg.msg);
erl_free_term(fromp); erl_free_term(tuplep);
erl_free_term(fnp); erl_free_term(argp);
erl_free_term(resp);
}
}
}
}
int my_listen(int port) {
int listen_fd;
struct sockaddr_in addr;
int on = 1;
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (-1);
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
memset((void*) &addr, 0, (size_t) sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
return (-1);
listen(listen_fd, 5);
return listen_fd;
}编译项目后,会生成cnode.exe的程序。这里要先启动erlang epmd服务,再跑这个程序。原因是erlang节点之间的通讯要依赖一个底层的端口映射服务epmd,这个模块的主要功能是提供通过相互通过name来识别机器的机制。
7、启动erlang epmd服务
可以先在本机启动一个erlang节点,erlang会自动起这个epmd服务。demo中也带了这个程序epmd.exe,手动执行即可
8、运行erlang节点
C:\>erl -name e1@127.0.0.1 -setcookie secretcookie
Eshell V5.10.3 (abort with ^G)
(e1@127.0.0.1)1> net_kernel:connect('cnode@127.0.0.1').
true
(e1@127.0.0.1)2> {any, 'cnode@127.0.0.1'} ! {call, self(), {bar, 3}}.
{call,<0.36.0>,{bar,3}}
(e1@127.0.0.1)3> flush().
Shell got {cnode,6}
ok
(e1@127.0.0.1)4> {any, 'cnode@127.0.0.1'} ! {call, self(), {foo, 3}}.
{call,<0.36.0>,{foo,3}}
(e1@127.0.0.1)5> flush().
Shell got {cnode,4}
ok完整demo下载:http://download.csdn.net/detail/cwqcwk1/8126053
demo无法编译或无法起来的原因?
之前写过nif的例子,有网友表示demo无法跑起来,这里总结其中的情况:
1、demo的erlang版本是R16B02,必须使用这个版本的erlang,否则会有问题。下载页
2、我的编译器是vs2010,必须安装有vs2010以上的编译器。如果没有安装,只是想运行这个demo需要安装vc2010运行库
3、epmd服务未启动,demo中自带了epmd.exe,双击即可。或者先在本机启动一个erlang节点,erlang会自动起这个服务。‘
4、其他erlang节点之间无法通讯的原因,还有cookie、名字问题,参考这篇文章
上面讲的是CNode做服务端节点的例子,下面也贴下CNode做客户端节点的代码:int main(int argc, char **argv) {
int fd; /* fd to Erlang node */
int loop = 1; /* Loop flag */
int got; /* Result of receive */
unsigned char buf[BUFSIZE]; /* Buffer for incoming message */
ErlMessage emsg; /* Incoming message */
ETERM *fromp, *tuplep, *fnp, *argp, *resp;
int res;
erl_init(NULL, 0);
if (erl_connect_init(1, "secretcookie", 0) == -1)
erl_err_quit("erl_connect_init");
if ((fd = erl_connect("e1@idril")) < 0)
erl_err_quit("erl_connect");
fprintf(stderr, "Connected to ei@idril\n\r");
while (loop) {
got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);
if (got == ERL_TICK) {
/* ignore */
} else if (got == ERL_ERROR) {
loop = 0;
} else {
if (emsg.type == ERL_REG_SEND) {
fromp = erl_element(2, emsg.msg);
tuplep = erl_element(3, emsg.msg);
fnp = erl_element(1, tuplep);
argp = erl_element(2, tuplep);
if (strncmp(ERL_ATOM_PTR(fnp), "foo", 3) == 0) {
res = foo(ERL_INT_VALUE(argp));
} else if (strncmp(ERL_ATOM_PTR(fnp), "bar", 3) == 0) {
res = bar(ERL_INT_VALUE(argp));
}
resp = erl_format("{cnode, ~i}", res);
erl_send(fd, fromp, resp);
erl_free_term(emsg.from); erl_free_term(emsg.msg);
erl_free_term(fromp); erl_free_term(tuplep);
erl_free_term(fnp); erl_free_term(argp);
erl_free_term(resp);
}
}
}
}代码就参照上面的方法编译了
最后,如果对erlang有什么问题或者对某些技术感兴趣的,都可以回帖告诉我。我看到就会找时间研究一下,做一个分享或讨论。
扩展阅读:
erlang与java构建的节点通讯
erlang节点通讯例子及问题分析
erlang在windows下和虚拟机节点通信
Windows下使用NIF扩展Erlang方法
参考:http://blog.csdn.net/mycwq/article/details/40836273 http://www.erlang.org/doc/tutorial/cnode.html
相关文章推荐
- Erlang与C构建的节点通讯
- Erlang与C构建的节点通讯
- erlang与java构建的节点通讯
- 利用jinterface在java和erlang节点之间通讯
- [Erlang]节点通讯的几种形式及问题分析
- erlang节点通讯例子及问题分析
- 第二部分 关于Cassandra1.0.x节点间通讯《草稿》
- 1个物理机同时搭建2个erlang虚拟节点,不能启用 +A600选项
- JS构建页面的DOM节点结构(二)
- 基于线程池和NIO技术构建高效的多协议Android通讯框架
- 构建插件式的应用程序框架(六)----通讯机制(ZT)
- MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制
- 课堂练习之链表节点删除与构建堆
- erlang和java的socket通讯----最简单,初次实现。
- Rebar:Erlang构建工具
- 6、Configuration构建之setting节点解析
- Rebar:Erlang构建工具
- [Erlang 0060] Joe Armstrong 论文《面向软件错误构建可靠的分布式系统》笔记
- 利用Socket来实现Erlang与C#之间的通讯
- C++构建循环链表(无头节点)