- 浏览: 337667 次
- 性别:
- 来自: 北京
最新评论
-
perfect_control:
真的很详细,一些东西很容易被我忽略掉了
使用fprof进行性能分析 -
leeyisoft:
http://www.erlangqa.com/ 怎么变成 “ ...
Erlang问答网站,欢迎各位提出问题,解答问题。 -
simsunny22:
4年之后我才看到 慢慢的干货
Erlang服务器内存耗尽bug跟踪过程 -
爱死我:
...
使用etop查看系统中进程信息 -
宋兵甲:
在跑这个服务的时候,每秒建立一个客户端连接,连续建立10000 ...
自己写一个tcp 通用服务器
好久不发文章,因为工作太忙。这个东西就凑凑数吧。各位见谅。
下一篇可能会介绍port,因为工作中用的比较多.
CNode用户指南
litaocheng |
litaocheng@gmail.com |
2009.7.8 |
1 概述
利用Erlang的 erl_interface ,我们可以构建自己的Erlang "Node",我们称为 "CNode ",erl_interface实现了基本的节点连接,以及消息发送接收,以及Erlang Term 的构建解析.
使用CNode,可以完成很多使用port完成的功能,区别是你的应用是一个c程序,而不需要 一个erlang应用.
CNode是hidden node,在erlang的 nodes() 结果中,无法看到CNode(可以通过nodes(connected)获取)
2 CNode 相关API
2.1 建立连接
erl_init(NULL, 0) 首先进行erlang环境的初始化,主要是内存的初始化. 随后进行C node的初始化,假如我们的C node name为short name, 调用 erl_connect_init(1, "secretcookie", 0) 则创建了一个名称为 c1 的C node. 如果要创建一个long name的C node,那么需要调用 erl_connect_xinit("idril", "cnode", "cnode@idril.ericsson.se", &addr, "secretcookie", 0); .
C node可以表现为一个client,也可以表现为一个srever.
- 作为client,调用 fd = erl_connect("e1@idril") 连接其他节点
- 作为server
- bind(),并listen一个本地端口
- 调用 erl_publish(port); 声明绑定的端口
- 调用 fd = erl_accept(listen, &conn); 等待client连接
2.2 发送接收消息
通过调用 erl_receive_msg() ,C node可以从Erlang节点接收消息.其通过建立连接时的fd接收消息. 接收的消息被存放在名为ErlMessage的结构中,ErlMessage的type字段表明接收的消息的类型,如 ERL_REG_SEND 表明 Erlang节点向C node中的某个registered process发送消息.ErlMessage的类型为ETerm的msg字段保存具体 的消息内容.
erl_receive_msg 可能会返回 ERL_ERROR (错误发生), ERR_TICK (节点心跳检测),还有和process link/unlink,以及 exit信号相关的返回值,需要我们注意.
代码片段如下:
while (loop) { got = erl_receive_msg(fd, buf, BUFSIZE, &emsg); if (got == ERL_TICK) { /* ignore */ } else if (got == ERL_ERROR) { loop = 0; /* exit while loop */ } else { if (emsg.type == ERL_REG_SEND) {
消息体为ETerm,可以使用erl_interface中的相关API进行操作.我们的示例中,消息体为 一个三元tuple,第二个元素为发送者的pid,第三个元素为tuple:{Function,Arg}. 计算的结果,通过 erl_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)); }
最后,所有创建ETerm相关内存,需要释放:
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); resp = erl_format("{cnode, ~i}", res); erl_send(fd, fromp, resp);
2.3 Erlang client
complex3:
-module(complex3). -export([foo/1, bar/1]). foo(X) -> call_cnode({foo, X}). bar(Y) -> call_cnode({bar, Y}). call_cnode(Msg) -> {any, c1@litao} ! {call, self(), Msg}, receive {cnode, Result} -> Result end.
3 编译运行
编译C node:
$ gcc -o cserver -I/usr/local/lib/erlang/lib/erl_interface-3.6.2/include \ -L/usr/local/lib/erlang/lib/erl_interface-3.6.2/lib \ complex.c cnode_s.c -g -rdynamic -lerl_interface -lei -lnsl -lpthread
启动epmd:
epmd -d -d #以debug方式启动
启动cserver:
./cserver 2342
至此C node启动完成,其绑定的本地端口为2342
启动client:
erl -sname t1
设置 c1@litao 的cookie,连接c1节点:
(t1@litao)6> erlang:set_cookie('c1@litao', 'secretcookie'). true (t1@litao)7> net_kernel:connect_node('c1@litao'). true (t1@litao)8> nodes(connected). [c1@litao]
执行调用:
(t1@litao)12> complex3:foo(3). 4
4 完整代码
cnode_s.c:
/* cnode_s.c */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include "erl_interface.h" #include "ei.h" #define BUFSIZE 1000 int main(int argc, char **argv) { 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; port = atoi(argv[1]); erl_init(NULL, 0); if (erl_connect_init(1, "secretcookie", 0) == -1) erl_err_quit("erl_connect_init"); /* 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); } } } /* while */ } 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; }
compex.c:
/* complex.c */ int foo(int x) { return x+1; } int bar(int y) { return y*2; }
评论
好的下次整理一下哦
发表评论
-
Erlang问答网站,欢迎各位提出问题,解答问题。
2012-03-18 15:07 5323平时收到很多关于Erlang的问题,我都尽量一一解答,可是时间 ... -
Emakefile并行编译
2011-11-17 13:15 7681项目代码越来越多,使用erlang编译也越来越慢。无论是Mak ... -
Erlang服务器内存耗尽bug跟踪过程
2011-10-25 21:44 21917本文描述朋友Erlang服务器内存耗尽bug的解决过程 ... -
inet:getstat/2小用法
2011-04-27 09:32 4603inet:getstat/2的用处 在 ... -
Erlang游戏开发-协议
2011-04-22 16:10 10745Erlang游戏开发-协议 ... -
Gearman Erlang Client
2010-10-17 21:14 3737Gearman Gearman是一个通用的任务调度框架。 ... -
ECUG归来
2010-10-17 21:02 2996今天ECUG V圆满结束了,不知不觉作为讲师已经参加过3次大会 ... -
gen-erl-app快速生成erlang app 框架
2010-04-07 14:22 4017经常需要创建各种erlang app,这个过程一旦掌握,就很繁 ... -
erl-redis发布
2010-03-30 11:44 5809最近几天因为需要,实现了一个redis erlang clie ... -
用Erlang做了很多事
2010-01-19 14:08 5101因为工作及时间关系,最近比较忙碌,没有太多的时间写文章。 ... -
ecug topic - erlang开发实践
2009-11-11 10:04 3777从ecug归来,感觉不错,大家学习探讨的积极性很高哦。 很高 ... -
reltool用户指南
2009-11-02 22:27 6412说明,最近比较忙,没有太多时间更新blog,请各位朋友谅解. ... -
Erlang定时任务server (仿crontab语法)
2009-09-23 18:03 6400好久不写blog了,看到yufeng老大那么活跃,我也“耐不住 ... -
Erlang进程之错?
2009-07-27 15:06 3709前阵子erlang-china关于erla ... -
Erlang类型及函数声明规格
2009-06-08 22:41 9590Erlang类型及函数声明 ... -
使用etop查看系统中进程信息
2009-05-29 13:57 6200Erlang提供了丰富的开发工具,你认为没有的时候,很可能是你 ... -
创建gen_server组解决单process瓶颈
2009-05-27 17:05 5299并发和顺序是一个令人 ... -
又有人投入Erlang的怀抱了:37Signals Campfire loves Erlang
2009-05-14 23:00 3698就喜欢看这样的东西... This is so juicy ... -
list random shuffle实现
2009-05-07 13:41 4370在项目中需要对list进行随机shuffle,但是在erlan ... -
Erlang开发建议(杂记版)
2009-04-24 18:27 6500以下是在erlang项目开发中的一些记录,即包含很多通俗易懂的 ...
相关推荐
**Erlang_CNode用户指南** 在IT领域,Erlang是一种面向并发的、函数式编程语言,由瑞典电信设备制造商Ericsson开发,主要用于构建高度可靠、可扩展的分布式系统。CNode是Erlang环境中的一个特殊概念,它是Erlang与...
Erlang_CNode用户指南通常会涵盖以下几个核心主题: 1. **安装和配置**:指导用户如何在系统上安装Erlang VM和CNode所需的所有依赖项,包括设置环境变量,确保编译器和链接器正确配置。 2. **创建CNode**:详细...
【标题】"cnode uni-app项目 + CNode:Node.js专业中文社区" 是一个基于Vue.js框架和uni-app开发的应用程序,旨在为Node.js开发者提供一个专业的中文交流平台。这个项目融合了多种技术特性和功能,如搜索、上拉加载更...
5. `README.md`:项目介绍和指南。 【Vue组件化开发】 Vue-cnode项目中,开发者将UI拆分为多个独立的组件,每个组件负责一部分功能和展示,如登录、论坛列表、帖子详情等。这种组件化开发方式提高了代码的可复用性...
8. **README.md**:可能包含项目的介绍、安装和使用指南,帮助开发者理解和运行项目。 开发微信小程序cnode社区版,需要对以下几个关键技术点有深入理解: - **微信小程序API**:微信提供了丰富的API,包括网络...
8. README或其他文档:提供项目介绍、安装指南、使用说明等。 综合以上分析,这个源码包对于想要了解或开发微信小程序,尤其是针对企业服务的开发者来说,是一个宝贵的资源。它涵盖了前端开发的各个方面,包括页面...
7. **Android Material Design**:应用可能采用了Material Design设计指南,提供了统一且富有层次感的UI元素和交互效果。 8. **Repository Pattern**:这是一种设计模式,用于处理数据源的抽象,可以是本地数据库、...
您可以在找到本指南的最新版本。目录自动格式化代码更改页面<title> 安装依赖项导入组件代码分割添加样式表后处理CSS 添加CSS预处理器(Sass,Less等) 添加图像,字体和文件使用public文件夹更改HTML 在模块...
该手册提供了一个全面的指南,用于理解内核服务与对象、能力空间、消息传递、线程与执行、地址空间、虚拟内存、硬件I/O、系统启动以及API参考等多个方面。 内核服务和对象章节主要介绍了内核提供的功能,包括基于...
Dim XMLDOM, node, Cnode, Cnode1, msginfo Thisurl = "http://" & Request.ServerVariables("HTTP_HOST") 'Response.Clear 'Response.CharSet = "UTF-8" 'Response.ContentType = "text/xml" Call IndexSiteMap("/...
压缩包内的“说明.txt”文件很可能是详细的操作指南,指导用户如何下载并应用新的BIOS更新,以及如何在BIOS中进行上述调整。而“EFI”文件夹则包含实际的BIOS更新文件,通常需要通过主板的UEFI BIOS升级工具来安装。...