我开始使用ZeroMQ for IPC并制作了一个简单的echo-client/server,我对一件事情感到惊讶.这是C++代码(使用zmq.hpp
和zmq_addon.hpp
).
服务器:
zmq::context_t context(1); zmq::socket_t socket(context, ZMQ_REP); socket.bind("ipc:///tmp/machine-1"); while (1) { zmq::multipart_t m; m.recv(socket); int i = m.poptyp(); i++; m.addtyp (i); m.send(socket); }
客户:
zmq::context_t context(1); zmq::socket_t socket(context, ZMQ_REQ); socket.connect("ipc:///tmp/machine-1"); int i = 0; while (1) { int save = i; zmq::multipart_t m; m.addtyp(i); m.send(socket); m.recv(socket); i = m.poptyp (); if (i != (save + 1)) break; if ((i % 100000) == 0) std::cerr << "i : " << i<< "\n"; }
我按预期工作.客户端发送一个int
,服务器加一个并发回.
现在我不明白的魔力:我意识到,我可以并行运行几次客户端,并且它会继续正常工作,为每个客户端正确.
比较检验save+1
,以i
始终确定.
ZMQ如何处理服务器端的并发问题?它如何知道响应必须发送回哪个客户端?
SO上有这个问题,但它没有回答我的问题:ipc://上的ZeroMQ REQ/REP和并发
根据zeromq文档,当您在服务器中调用REP.recv()时,它将从排队的REQ(客户端)套接字返回一条消息.如果连接了多个客户端,它将使用公平队列策略来选择一个.当您调用REP.send()进行回复时,REP套接字始终将响应发送到相应的REQ客户端.
这就是"魔术" - REP套接字负责将响应发送到正确的客户端.如果客户端已断开连接,则只删除回复消息.
该文档可能会比我更清楚的解释:
ZMQ_REP:服务使用ZMQ_REP类型的套接字从客户端接收请求并向客户端发送回复.此套接字类型仅允许zmq_recv(请求)和后续zmq_send(回复)调用的交替序列.收到的每个请求都是从所有客户端中排队等待的,并且每个发送的回复都会路由到发出最后一个请求的客户端.如果原始请求者不再存在,则回复将被静默丢弃.