Erlang C 节点相关问题

Posted

技术标签:

【中文标题】Erlang C 节点相关问题【英文标题】:Erlang C node related question 【发布时间】:2009-12-23 20:04:57 【问题描述】:

在提供的教程中: http://www.erlang.org/doc/tutorial/cnode.html

有以下例子:


/* cnode_s.c */
#include 
#include 
#include 
#include 
#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)) 

我怀疑 erl_receive_msg 是一个阻塞调用,我不知道如何克服这个问题。在C网络编程中有“select”语句,但在Erlang EI API中我不知道是否有这样的语句。

基本上我想构建一个 C 节点,不断向 Erlang 节点发送消息。为简单起见,假设只有一个 Erlang 节点。

Erlang 节点必须处理它从 C 节点接收到的消息。 Erlang 节点不应该确保它已经接收到消息,而不是它必须用处理结果来回复。因此,一旦发送了消息,我就不再关心它的信仰了。

有人可能认为可以将代码修改为:

... 如果(emsg.type == ERL_REG_SEND) ... 而(1) //生成元组 erl_send(fd, fromp, 元组); //释放分配资源 ...

这将产生一个无限循环,我们在其中生产和消费(发送)消息。 但是有一个重要的问题:如果我这样做,那么C节点可能会向Erlang节点发送过多的消息(所以应该有办法从Erlang节点向C节点发送消息以减慢速度),或者Erlang 节点可能认为 C 节点已关闭。

我知道问题一定很短(这又长又丑),但总结一下:

可以使用什么机制(过程调用、算法)在 C 中为 Erlang 中的懒惰消费者开发一个急切的生产者,以便双方都知道底层上下文?

【问题讨论】:

【参考方案1】:

对于您描述的情况,我自己使用端口驱动程序(没有触及 C 节点,因为我宁愿进行更多解耦)。

查看 Erlang 的端口驱动程序库:EPAPI。有一个项目利用了这个库:Erland DBus。

【讨论】:

问题是生产者是C节点,Erlang节点是消费者。我考虑过使用端口的想法,但是在连续循环中调用端口驱动程序的服务似乎不是最好的方法。 @zalmoxis:有很多不同的方法可以解决这种情况,其中一种可能是使用“基于令牌的信用算法”。 “消费者节点”向生产者节点发送“信用”。每个“发送”都需要一个“信用”:当没有更多信用时,“生产者”必须等待下一次“交付”信用。 @zalmoxis:我上面描述的“基于令牌的整形器”可以很容易地在“生产者”端(用 C 编写)实现,同时在 Erlang 端添加对该方案的支持同样微不足道.既然您已经使用“C 节点”来“痛苦”,那么我知道您可以使用端口驱动程序。干杯,玩得开心! (无论如何,一如既往,将我的贡献视为您考虑的建议)。【参考方案2】:

你检查ei_receive_msg_tmo 函数了吗?我想它的工作原理类似于 Erlang 的接收后构造,所以如果你将超时设置为 0,它将是非阻塞的。

我相信 erl_interface 已被弃用,应该使用 ei 代替。不过,这可能是一个完全错误的信息......

【讨论】:

谢谢,我正在测试它。请注意,通过使用超时 0 调用 ei_receive_msg_tmo 会阻塞。 好的。因此,显然非超时函数会退回到 ms=0 的超时函数。这就是为什么 ms=0 变成阻塞的原因(参见 ei_read_t() 函数 erl_interface/src/misc/ei_portio.c)。我认为这是懒惰对功能的胜利:)【参考方案3】:

您需要仔细查看您发布的教程链接。 (搜索“最后我们有了 C 节点客户端的代码。”)你会看到作者提供了一个客户端 cnode 实现。看起来很理性。

【讨论】:

以上是关于Erlang C 节点相关问题的主要内容,如果未能解决你的问题,请参考以下文章

认证失败(被远程节点拒绝),请检查 Erlang cookie

Erlang:不允许的节点/也许 Cookie 问题

在erlang中向远程节点端口发送消息

Phoenix/Erlang 节点连接

Erlang:以编程方式启动远程节点

如何连接到已注册的节点(Erlang)并从另一个 erlang 应用程序中使用它