【问题标题】:Why a zmq REQ-REP not working?为什么 zmq REQ-REP 不起作用?
【发布时间】:2017-06-19 12:34:24
【问题描述】:

我有 1 个主(使用 REQ)和 2 个从属(A、B)使用 REP。 master 向其中一个 slave 发送一个请求,并期待他的响应。

即使我在 ZMQ 信封中设置了地址,消息也被发送到了错误的从站。如何指定从机地址?我认为我在 master 中正确设置了它,但它无法正常工作并以循环方式发送来自 master 的请求。


ma​​ster.cpp

#include "zhelpers.hpp"
#include <string>

int main (int argc, char *argv[])
{
    zmq::context_t context(1);
    zmq::socket_t requester(context, ZMQ_REQ);
    requester.setsockopt(ZMQ_IDENTITY,"M");
    requester.bind("tcp://*:5559");

    for( int request = 0 ; request < 10 ; request++) {

        std::string cmd;
        std::cin>>cmd;
        s_sendmore (requester, "B");
        s_sendmore (requester, "");
        s_send (requester, cmd);
        s_dump(requester);
    }
}

slaveA.cpp

#include "zhelpers.hpp"

int main (int argc, char *argv[])
{
    zmq::context_t context(1);
    zmq::socket_t responder(context, ZMQ_REQ);
    responder.setsockopt(ZMQ_IDENTITY, "A", 1);
    responder.connect("tcp://localhost:5559");
    while(1)
    {
        s_dump(responder);
        sleep (1);//
//        s_sendmore (responder, "M"); //Should I set this ??
//        s_sendmore (responder, "");
        s_send (responder, "FromSlaveA");
    }
}

slaveB.cpp

#include "zhelpers.hpp"

int main (int argc, char *argv[])
{
    zmq::context_t context(1);
    zmq::socket_t responder(context, ZMQ_REP);
    responder.setsockopt(ZMQ_IDENTITY, "B", 1);
    responder.connect("tcp://localhost:5559");

    while(1)
    {
        s_dump(responder);
        sleep (1);
        s_send (responder, "FromSlaveB");
    }
}

怎么了? 操作系统:Ubuntu 16.04,ZMQ 版本 4.X.X


更新 1:

将 slaveA 套接字更改为 REP,但 master 仍以循环方式向 slaveA 和 SlaveB 发送消息。现在,我想我是否将消息信封正确设置为 slaveB ?但是当我打印信封时,我在slave's得到了这个证明我正确地将信封设置为B,不是吗?

[001]B
[000]
[005]jjjjj

【问题讨论】:

    标签: c++ network-programming zeromq distributed-computing


    【解决方案1】:

    您的 slaveA.cpp 应该使用正确的 ZeroMQ 接入点原型:

    zmq::socket_t responder( context, ZMQ_REP );    // !ZMQ_REQ);
    

    Post Festum:文档在产生问题之前要阅读两次

    ZMQ_IDENTITY:设置套接字标识

    当连接到ROUTER 套接字时,ZMQ_IDENTITY 选项应设置指定套接字的标识。标识的长度应为 1 到 255 个字节,并且可以包含任何值。

    如果两个客户端在连接到ROUTER 时使用相同的身份,则结果应取决于ZMQ_ROUTER_HANDOVER 选项设置。如果未设置(或设置为默认值零),ROUTER 套接字将拒绝尝试使用已使用身份连接的客户端。如果该选项设置为 1,ROUTER 套接字应将连接移交给新客户端并断开现有客户端。

    Option value type binary data
    Option value unit N/A
    Default value NULL
    Applicable socket types ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER.

    抱歉,
    这种 .setsockopt() 设置是:
    1) 这个功能有很好的文档记录,包含所有相关的操作细节和可能的使用概念
    2) 仅对于您的代码中不存在的对象才有意义
    3) 决定一个与您的代码无关的功能性行为
    4) 此功能与您的代码中存在的对象的硬连线循环传递绝对无关,用于传出流量。

    因此,请阅读文档,它“足够”并且是专业避免产生问题的公平方式。

    Q.E.D.

    【讨论】:

    • 即使它是一个 REQ 套接字,请求也应该去那里,因为信封有那个地址。正确吗?
    • 否定,先生。而是停止发明不属于(协议)API规范的功能。按照 API 定义的服务来设计东西是很常见的,而不是相反,不是吗?。
    • 我将首先尝试使用预定义的模式重新设计我的解决方案,但问题是,当信封具有该地址时,为什么不这样做。我是否正确定义了地址。
    • 我把slaveA的socket改成了REP,但是master还是把消息发送给slaveA,虽然我把地址设置成了slaveB,为什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    • 2014-01-03
    • 2023-03-14
    • 2014-01-16
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多