Node communication built by Erlang and C
The communication between Erlang nodes is mainly used for communication between two Erlang nodes. However, Erlang also supports communication with nodes built in java and even nodes built in c, the previous two methods have been mentioned in my previous articles, so here we will talk about the node communication between Erlang and c.
Cnode and erl_interface
To build an erlang node in C, you must use the erl_interface interface of Erlang. The node established by c is called a CNode. In addition to some basic node connections and message sending and receiving, erl_interface also implements the construction and parsing of Erlang Term.
CNode is another c extension erlang method except nif, but compared with nif, this method does not cause erlang crash, because they communicate through socket at the underlying layer in different processes.
Another problem is that CNode is hidden in the erlang cluster. Therefore, the node cannot be found using nodes () in erlang. However, after the node is connected successfully, it can be obtained through nodes (connected.
Communication between CNode and Erlang
The following describes how to use CNode to communicate with Erlang in Windows (demo download)
I. Preparations
1. Download the erlang binary installation package. Here R16B02 is used as an example.
2. After installing erlang, go to the installation directory to get the erlang header file and static library package:
Erl header file: erl5.10.3 \ lib \ erl_interface-3.7.14 \ include \
Erl static library: erl5.10.3 \ lib \ erl_interface-3.7.14 \ lib, static library here only use ei_md.lib and erl_interface_md.lib
2. Create a c Project
1. Create an empty project named cnode
2. Copy the include folder and lib folder to the project directory.
3. Modify project properties. Select the Unicode Character Set for the character set.
4. Modify project properties. Add "include" to the include directory of the VC ++ directory, and add "lib" to the library"
5. Add the project file cnode. c and save the following code:
# Include
# Include
# Ifdef _ WIN32 # define _ WIN32 __# include
# Pragma comment (lib, "ws2_32.lib") # pragma comment (lib, "ei_md.lib") # pragma comment (lib, "comment") # 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 // initialize the winsock service 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) = E RL_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 (strncm P (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 ;}
After compilation, the program cnode.exe will be generated. Start the erlang epmd service and then run the program. The reason is that the communication between erlang nodes depends on an underlying port ing service epmd. The main function of this module is to provide a mechanism to identify machines by name.
7. Start the erlang epmd Service
You can start an erlang node on the local machine. erlang automatically starts the epmd service. This program epmd.exe is also included in demoand can be manually executed.
8. Run the erlang Node
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
Complete demo download: http://download.csdn.net/detail/cwqcwk1/8126053
Why can't the demo be compiled or cannot be compiled?
I have previously written an example of nif. Some netizens said that the demo could not run. Here we will summarize the situation:
1. the erlang version of the demo is R16B02. You must use this version of erlang; otherwise, problems may occur. Download Page
2. My compiler is vs2010 and must be installed with a compiler later than vs2010. To run this demo, you must install the vc2010 Runtime Library.
3. When the epmdservice is not started, demohas epmd.exe, And you can double-click it. Or start an erlang node on the local machine. erlang will automatically start the service. '
4. Reasons why other erlang nodes cannot communicate with each other, as well as cookie and name issues. For details, refer to this article.
The above is an example of using CNode as a server node. The code for using CNode as a client node is also posted below:
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);}}}}
The code is compiled by referring to the above method.
Finally, if you have any questions about erlang or are interested in some technologies, you can reply to me. I will find time to study and share or discuss it.
Additional reading:
Node communication between erlang and java
Erlang node communication example and Problem Analysis
Erlang communicates with virtual machine nodes in windows
Using NIF to extend Erlang in Windows
Reference: http://blog.csdn.net/mycwq/article/details/40836273
Http://www.erlang.org/doc/tutorial/cnode.html