[英]How can I send a ZeroMQ message from a ROUTER socket to a specific DEALER socket using cppzmq?
我把這個最小的例子放在一起,以便將消息從路由器套接字發送到特定的DEALER socker(它有它的身份集)。 當運行這兩個程序時,它似乎掛在ROUTER 上等待來自DEALER的回復,而DEALER掛起等待來自ROUTER的請求。 因此,似乎ROUTER發送的消息從未發送到DEALER 。
路由器.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();
}
經銷商.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;
}
我最初認為我應該在消息前面加上一個空分隔符socket.send(zmq::message_t(), ZMQ_SNDMORE);
,但這導致了錯誤。 同樣使用以下內容也會導致在 try/catch 塊中拋出錯誤。 該錯誤只是打印“未知錯誤”:
zmq::message_t delimiter(0);
socket.send(delimiter, ZMQ_SNDMORE);
使用以下內容創建分隔符也會導致相同的錯誤:
socket.send(zmq::message_t(), ZMQ_SNDMORE);
據我所知,在使用 cppzmq 時,您不需要添加空分隔符(我可能錯了,但在閱讀並查看其他人的示例並測試我自己的代碼后,這是我確定的)。
這是一個非常基本的圖表,其中包含此設計的最終目標:
在我的研究中,我沒有找到這段代碼的好例子。 Cppzmq github 的文檔和示例很少。
以下是我看過的其他一些來源:
ROUTER/DEALER 模式的主要思想是它是 REPLY/REQUEST 的異步泛化。 然而,您正在嘗試反轉模式中的套接字,發現它不適合並扭曲代碼以嘗試使其適合。 不要那樣做。
你需要做的是“順其自然”。 在存在示例的簡單方法中,DEALER 應發送第一條消息。 然后路由器對此做出響應。
下一級別是讓 DEALER 在其啟動消息中標識自己。 ROUTER 然后可以給那個 DEALER 一個特定的響應。
在下一個級別,您可以真正實現異步。 ROUTER 可以獲取每個 DEALER 的標識消息的副本,並使用消息副本隨時向任何 DEALER 發送異步消息。 標識消息的一份副本將附加“PEER2”幀並發送給經銷商。 這是有效的,因為消息的副本包括路由幀。 理想情況下,您還可以刪除“消息”幀,只在副本中保留路由幀。
警告 - 我不使用 cppzmq,我使用 CZMQ。 我可以說使用 CZMQ 這種幀操作非常容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.