简体   繁体   English

如何使用 cppzmq 从 ROUTER 套接字向特定的 DEALER 套接字发送 ZeroMQ 消息?

[英]How can I send a ZeroMQ message from a ROUTER socket to a specific DEALER socket using cppzmq?

I've put together this minimal example in order to send a message from a Router socket to a specific DEALER socker (That has it's identity set).我把这个最小的例子放在一起,以便将消息从路由器套接字发送到特定的DEALER socker(它有它的身份集)。 When running these two programs it appears to hang on the ROUTER waiting from the reply from the DEALER , and the DEALER hangs waiting for the request from the ROUTER .当运行这两个程序时,它似乎挂在ROUTER 上等待来自DEALER的回复,而DEALER挂起等待来自ROUTER的请求。 So it appears that the message that the ROUTER is sending is never making it to the DEALER .因此,似乎ROUTER发送的消息从未发送到DEALER

Router.cpp路由器.cpp

#include <iostream>
#include <zmq.hpp>
#include <string>
#include <thread>
#include <chrono>

int main() {
    zmq::context_t context;
    zmq::socket_t socket (context, zmq::socket_type::router);
    // Enforce sending routable messages only
    socket.setsockopt(ZMQ_ROUTER_MANDATORY, 1);
    socket.bind("tcp://*:5555");

    try {
        std::string jobRequest = "ExampleJobRequest";

        std::cout << "Router: Sending msg: " << jobRequest << std::endl;

        // Set the address, then the empty delimiter and then the request itself
        socket.send("PEER2", ZMQ_SNDMORE);
        //socket.send(zmq::message_t(), ZMQ_SNDMORE);
        socket.send(zmq::str_buffer("ExampleJobRequest")) ;

        // Set the address, then the empty delimiter and then the request itself
        socket.send("PEER2", ZMQ_SNDMORE);
        //socket.send(zmq::message_t(), ZMQ_SNDMORE);
        socket.send(zmq::str_buffer("ExampleJobRequest")) ;

        // Receive the reply from the camera
        std::cout << "Router: Waiting for reply from camera " << std::endl;
        zmq::message_t reply;
        socket.recv(&reply);

        std::cout << "Router: Received " <<  std::string(static_cast<char*>(reply.data()), reply.size()) << std::endl;
    } catch (std::exception e) {
        std::cout << "Router Error: " << e.what();
    }

    std::this_thread::sleep_for(std::chrono::seconds(1));
    socket.close();
    context.close();
}

Dealer.cpp经销商.cpp

#include <zmq.hpp>
#include <string>
#include <iostream>
#include <thread>

int main (void)
{
    //  Prepare our context and socket
    zmq::context_t context;
    zmq::socket_t socket (context, zmq::socket_type::dealer);

    std::cout << "Dealer: Connecting to RunJob server… \n";
    socket.setsockopt(ZMQ_IDENTITY, "PEER2", 5);
    socket.connect ("tcp://localhost:5555");

    while(true) {
        try {
            // Wait for next request from client
            std::cout << "Dealer: Waiting for request" << std::endl;
            zmq::message_t request;
            zmq::message_t empty;

            // Receive request
            socket.recv(&request);

            std::string requestString = std::string(static_cast<char*>(request.data()), request.size());

            std::cout << "Dealer: Received request" << std::endl;
            std::cout << requestString << std::endl;

            // ZMQ_SNDMORE - "Specifies that the message being sent is a multi-part message, and that further message parts are to follow"
            socket.send(zmq::str_buffer("Job completed"), zmq::send_flags::dontwait);
        }catch (std::exception e) {
            std::cout << "Router Error: " << e.what();
        }
    }

    // Used to set various 0MQ Socket Settings
    // ZMQ_Linger - Set linger period for socket shutdown
    socket.setsockopt(ZMQ_LINGER, 0);
    socket.close();
    context.close();

    return 0;
}

I had originally considered that I should be prepending the message with an empty delimiter, socket.send(zmq::message_t(), ZMQ_SNDMORE);我最初认为我应该在消息前面加上一个空分隔符socket.send(zmq::message_t(), ZMQ_SNDMORE); , but this caused an error. ,但这导致了错误。 Also using the following also caused an error to be thrown in the try/catch block.同样使用以下内容也会导致在 try/catch 块中抛出错误。 The error simply prints 'Unknown error':该错误只是打印“未知错误”:

zmq::message_t delimiter(0);
socket.send(delimiter, ZMQ_SNDMORE);

Using the following to create the delimiter also causes the same error:使用以下内容创建分隔符也会导致相同的错误:

socket.send(zmq::message_t(), ZMQ_SNDMORE);

To my knowledge, when using cppzmq you don't need to add the empty delimiter (I could be wrong about this, but after reading around and looking at other peoples example and testing my own code, this is what i determined).据我所知,在使用 cppzmq 时,您不需要添加空分隔符(我可能错了,但在阅读并查看其他人的示例并测试我自己的代码后,这是我确定的)。

Here's a very basic diagram with the end goal of this design :这是一个非常基本的图表,其中包含此设计的最终目标:

路由器到经销商的消息传递设计

In my research, i haven't found a good example of this code.在我的研究中,我没有找到这段代码的好例子。 The Cppzmq github has very little documentation and few examples. Cppzmq github 的文档和示例很少。

Here are some other sources i've looked at:以下是我看过的其他一些来源:

The main idea about ROUTER/DEALER pattern is that it is an asynchronous generalisation of REPLY/REQUEST. ROUTER/DEALER 模式的主要思想是它是 REPLY/REQUEST 的异步泛化。 Yet you are trying to reverse the sockets in your pattern, discovering it doesn't fit and contorting the code to try and make it fit.然而,您正在尝试反转模式中的套接字,发现它不适合并扭曲代码以尝试使其适合。 Don't do that.不要那样做。

What you need to do is "go with the flow".你需要做的是“顺其自然”。 In the simple method, for which examples exist, the DEALER should send the first message.在存在示例的简单方法中,DEALER 应发送第一条消息。 The ROUTER then responds to that.然后路由器对此做出响应。

The next level is for the DEALER to identify itself in its startup message.下一级别是让 DEALER 在其启动消息中标识自己。 The ROUTER can then give a specific response to that DEALER. ROUTER 然后可以给那个 DEALER 一个特定的响应。

At the next level you can go truly asynchronous.在下一个级别,您可以真正实现异步。 The ROUTER can take a copy of each DEALER's identification message, and use the message copies to send asynchronous messages to any DEALER at any time. ROUTER 可以获取每个 DEALER 的标识消息的副本,并使用消息副本随时向任何 DEALER 发送异步消息。 One copy of the identification message would have the "PEER2" frame appended to it and sent to the DEALER.标识消息的一份副本将附加“PEER2”帧并发送给经销商。 This works because the copies of the messages include the routing frames.这是有效的,因为消息的副本包括路由帧。 Ideally, you would also strip the 'message' frames, to leave only the routing frames in the copy.理想情况下,您还可以删除“消息”帧,只在副本中保留路由帧。

Caveat - I don't use cppzmq, I use CZMQ.警告 - 我不使用 cppzmq,我使用 CZMQ。 I can say that using CZMQ this sort of frame manipulation is very easy.我可以说使用 CZMQ 这种帧操作非常容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM