Erlang與C構建的節點通訊

來源:互聯網
上載者:User

標籤:des   style   blog   http   io   ar   os   使用   java   

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 8088int 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", "[email protected]",&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 [email protected] -setcookie secretcookie Eshell V5.10.3 (abort with ^G) ([email protected])1> net_kernel:connect(‘[email protected]‘). true ([email protected])2> {any, ‘[email protected]‘} ! {call, self(), {bar, 3}}. {call,<0.36.0>,{bar,3}} ([email protected])3> flush(). Shell got {cnode,6} ok ([email protected]0.0.1)4> {any, ‘[email protected]‘} ! {call, self(), {foo, 3}}. {call,<0.36.0>,{foo,3}} ([email protected])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("[email protected]")) < 0)erl_err_quit("erl_connect");fprintf(stderr, "Connected to [email protected]\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構建的節點通訊

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.