Tcp 如何使用ZeroMQ开发简单的经销商/路由器消息流?

Tcp 如何使用ZeroMQ开发简单的经销商/路由器消息流?,tcp,zeromq,Tcp,Zeromq,我对TCP消息传递(以及一般的编程)相当陌生,我正在尝试使用ZeroMQ开发一个简单的路由器/经销商消息对,但我很难让路由器接收来自经销商的消息并将其发送回 我可以毫无问题地执行一个简单的REQ/REP模式,从我的机器向我的虚拟机发送一条消息 但是,当尝试开发一个路由器/经销商对时,我似乎无法让路由器-实例接收消息(VM上的路由器,主框上的经销商)。我已经取得了一些成功,我可以在while(){…}循环中垃圾邮件发送50条消息,但不能发送一条消息,也不能让路由器发回一条 因此,从我所读到的内容来

我对TCP消息传递(以及一般的编程)相当陌生,我正在尝试使用ZeroMQ开发一个简单的路由器/经销商消息对,但我很难让路由器接收来自经销商的消息并将其发送回

我可以毫无问题地执行一个简单的
REQ/REP
模式,从我的机器向我的虚拟机发送一条消息

但是,当尝试开发一个
路由器/经销商
对时,我似乎无法让
路由器
-实例接收消息(VM上的
路由器
,主框上的
经销商
)。我已经取得了一些成功,我可以在
while(){…}
循环中垃圾邮件发送50条消息,但不能发送一条消息,也不能让
路由器
发回一条

因此,从我所读到的内容来看,
路由器/经销商
对中的TCP消息以0作为分隔符发送,并且必须首先将该0发送到
路由器
以注册传入消息

所以我只想将消息“ROUTER_TEST”发送到我的服务器,让服务器以“RECEIVED”响应

经销商

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“zmq.h”
常量字符连接[]=”tcp://10.0.10.76:5555";
内部主(空)
{
int大调、小调、面片;
zmq_版本(主、次、补丁);
printf(“\n安装的ZeroMQ版本:%d.%d.%d\n”,主要、次要、修补程序);
printf(“连接到:%s\n”,连接);
void*context=zmq_ctx_new();
void*requester=zmq_套接字(上下文,zmq_交易商);
int zc=zmq_connect(请求者,连接);

欢迎来到零之禅

如果您从未使用过ZeroMQ,
您可能会喜欢在深入了解更多细节之前先看一看

您的代码在经销商侧调用一系列:

void *requester = zmq_socket( context,
                              ZMQ_DEALER           // <--   .STO <ZMQ_DEALER>, *requester
                              );
...
int n   = zmq_send( requester, // <~~ <~~ <~~ <~~ <~~ <~~   .STO 0, n
                    NULL,     //                             NULL,sizeof(NULL)== 0
                    0,       //                              explicitly declared 0
                    ZMQ_DONTWAIT                   //           _DONTWAIT flag
                  | ZMQ_SNDMORE                    //---- 1x ZMQ_SNDMORE  flag== 
                    );                             //        1.Frame in 1st MSG
int ii  = 0;                                       //        MSG-under-CONSTRUCTION
if ( n == 0 )                                      //     ...until complete, not yet sent
{    
     std::cout << "PREVIOUS[" << ii << ".] CALL of zmq_send() has returned n = " << n << std::endl;

     while ( ii < 50 )
     {       ii++;
             n = zmq_send( requester,   //---------//---- 1x ZMQ_SNDMORE following
                           messageSend, //         //        2.Frame in 1st MSG
                           31,          //         //        MSG-under-CONSTRUCTION, but
                           ZMQ_DONTWAIT //         //        NOW complete & will get sent
                           );           //---------//----49x monoFrame MSGs follow
     }
}
...
在这里,最有可能的是,
rc==0
,但如果没有遗漏,则只会出现一次,但不会出现更多 请注意,您的代码不会以任何方式检测到
.recv()
-调用是否也被
ZMQ\u RECVMORE
-标记需要首先也
.recv()
-第一条消息的所有剩余多帧部分,然后才能
.send()
-任何答案

处理多部分消息的应用程序在调用
ZMQ_recv()
后,必须使用
ZMQ_RCVMORE
ZMQ_getsockopt(3)
选项来确定是否还有其他部分要接收

接下来,缓冲区和消息发送——“有效载荷”是一种脆弱的实体,应该重新组合(有关详细信息,请再次阅读所有有关如何小心初始化、使用和安全触摸任何对象的详细信息),正如成功的
.send()/.recv()
后一样,低级API(因为2.11.x+)认为它们已被丢弃,不可重复使用。还要注意的是,
messageSend
不是(必须放在代码中)31-
字符[]
-长,是吗?有什么特别的意图这样做吗

zmq\u send()
函数如果成功,将返回消息中的字节数。否则,它将返回
-1
,并将
errno
设置为以下定义的值之一。
{EAGAIN,ENOTSUP,EINVAL,EFSM,etem,ENOTSOCK,EINTR,ehostunich}

不测试错误状态意味着不知道
REQ/REP
DEALER/ROUTER
(扩展)
.send()/.recv()/.send()/.recv()/…
的实际状态(请参阅
EFSM
和其他潜在故障解释程序)
强制dFSA执行这些步骤的顺序


“因此,从我所读到的内容来看,
路由器/经销商
对中的TCP消息在开始时使用分隔符0发送,并且必须首先将此0发送到
路由器
以注册传入消息。”


这似乎是一个错误的部分。应用程序端可以自由地编写任意数量的单帧或多帧消息,但是
路由器
预挂身份帧的“技巧”在没有用户帮助的情况下执行(消息标签在任何(现在,主要是所有)多帧(d)之前自动执行)消息被传递到应用程序端(使用接收方端的
.recv()
-方法)。上面提到了对多帧消息的适当处理。

欢迎来到Zen of Zero

如果您从未使用过ZeroMQ,
您可能会喜欢在深入了解更多细节之前先看一看

您的代码在经销商侧调用一系列:

void *requester = zmq_socket( context,
                              ZMQ_DEALER           // <--   .STO <ZMQ_DEALER>, *requester
                              );
...
int n   = zmq_send( requester, // <~~ <~~ <~~ <~~ <~~ <~~   .STO 0, n
                    NULL,     //                             NULL,sizeof(NULL)== 0
                    0,       //                              explicitly declared 0
                    ZMQ_DONTWAIT                   //           _DONTWAIT flag
                  | ZMQ_SNDMORE                    //---- 1x ZMQ_SNDMORE  flag== 
                    );                             //        1.Frame in 1st MSG
int ii  = 0;                                       //        MSG-under-CONSTRUCTION
if ( n == 0 )                                      //     ...until complete, not yet sent
{    
     std::cout << "PREVIOUS[" << ii << ".] CALL of zmq_send() has returned n = " << n << std::endl;

     while ( ii < 50 )
     {       ii++;
             n = zmq_send( requester,   //---------//---- 1x ZMQ_SNDMORE following
                           messageSend, //         //        2.Frame in 1st MSG
                           31,          //         //        MSG-under-CONSTRUCTION, but
                           ZMQ_DONTWAIT //         //        NOW complete & will get sent
                           );           //---------//----49x monoFrame MSGs follow
     }
}
...
在这里,最有可能的是,
rc==0
,但如果没有遗漏,则只会出现一次,但不会出现更多 请注意,您的代码不会以任何方式检测到
.recv()
-调用是否也被
ZMQ\u RECVMORE
-标记需要首先也
.recv()
-第一条消息的所有剩余多帧部分,然后才能
.send()
-任何答案

处理多部分消息的应用程序在调用
ZMQ_recv()
后,必须使用
ZMQ_RCVMORE
ZMQ_getsockopt(3)
选项来确定是否还有其他部分要接收

接下来,缓冲区和消息发送——“有效载荷”是一种脆弱的实体,应该重新组合(有关详细信息,请再次阅读所有有关如何小心初始化、使用和安全触摸任何对象的详细信息),在成功执行
.send()之后