3

我在 ZMQ 中设置了一个 REP/DEALER 连接,发现当 REP 向 DEALER 发送一条消息时,后者必须接收两次才能获取消息。为什么是这样?

复制此代码的代码是此 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()
4

1 回答 1

8

我是 RTFM,答案是:ZMQ 与 REP 套接字之间的消息都包含在信封中。因此,在底层,REP 需要一个带有分隔符的消息,然后是消息内容;然后,它去掉分隔符,只将内容返回给应用程序。这就是为什么经销商会发送这样的消息:

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

,因为 REP 期望那里的分隔符会被剥离,而 DEALER 不会自动为我们执行此操作。

现在,当 REP 向 DEALER 发送回消息时,情况正好相反。在应用程序中,看起来我们只是发送数据而没有任何额外内容:

socket.send("world")

但是,REP 套接字在前面添加了一个分隔符,以便消息“在一个信封中”发送,就像收到它一样。

那么,为什么DEALER需要接收两次呢?

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

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

来源:

于 2013-05-22T14:30:22.690 回答