为什么我需要为发送到zmq.DEALER的每条消息收到两次?

时间:2013-05-22 13:16:01

标签: zeromq pyzmq

我在ZMQ中设置了一个REP / DEALER连接,发现当REP向DEALER发送一个msg时,后者必须重新两次才能获得该消息。 为什么会这样?

复制它的代码是代码from this SO answer的修改版本。他们的代码每个工人只收到一次,但我测试了这个,我只回到了一个“世界”。我不得不接受四次以获得2个“世界”,因此:

import zmq
import time
import sys
import threading

SOCKET_NAME = "tcp://127.0.0.1:8000"
#SOCKET_NAME = "inproc://mysocket"

def dealerRoutine(context):
    socket = context.socket(zmq.DEALER)
    socket.bind(SOCKET_NAME)
    time.sleep(1)
    socket.send("", zmq.SNDMORE)
    socket.send("hello")
    socket.send("", zmq.SNDMORE)
    socket.send("hello")
    print "first msg", socket.recv()
    print "second msg", socket.recv()
    print "third msg", socket.recv()
    print "fourth msg", socket.recv()
    socket.close()


def workerRoutine(context):
    socket = context.socket(zmq.REP)
    socket.connect(SOCKET_NAME)
    s = socket.recv()
    print "worker received", s
    socket.send("world")

context = zmq.Context()

workers = []
for i in range(0, 2):
    worker = threading.Thread(target=workerRoutine, args=([context]))
    workers.append(worker) 
    worker.start()

dealerRoutine(context)

for worker in workers:
    worker.terminated = True

context.term()

1 个答案:

答案 0 :(得分:7)

我是RTFM,答案是:来自REP套接字的ZMQ消息包含在信封中。因此,在引擎盖下,REP需要一个带分隔符的消息,然后是消息内容;然后,它删除分隔符并仅将内容返回给应用程序。这就是DEALER发送这样的消息的原因:

socket.send("", zmq.SNDMORE)
socket.send("hello")

,因为REP希望那里的分隔符会被剥离而且DEALER不会自动为我们做。

现在,当REP将消息发送回DEALER时,反之亦然。在应用程序中,看起来我们只是在没有任何额外的情况下发送数据:

socket.send("world")

然而,REP套接字在前面添加了一个分隔符,这样就可以像收到信息一样“在一个信封里”发送消息。

那么,为什么经销商需要接收两次?

因为,与REP不同,DEALER不会隐式处理分隔符。它保持一切正常。因此,既然我们知道它是从REP套接字接收的,我们可以安全地接收两次,一个用于删除自己的分隔符,另一个用于实际获取数据:

socket.recv() # discard delimiter
our_data = socket.recv()

来源: