3

ZMQ で REP/DEALER 接続をセットアップしたところ、REP が 1 つのメッセージを DEALER に送信すると、DEALER はメッセージを取得するために 2 回受信する必要があることがわかりました。どうしてこれなの?

これを複製するコードは、この SO answerのコードの修正版です。彼らのコードはワーカーごとに 1 回しか受信しませんが、これをテストしたところ、1 つの「ワールド」しか返されませんでした。2つの「世界」を取り戻すには、4回受け取る必要がありました。

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

I RTFM の答えは次のとおりです。REP ソケットとの間の ZMQ メッセージはエンベロープに含まれています。そのため、内部では、REP は区切り文字とメッセージの内容を含むメッセージを期待しています。次に、区切り文字を取り除き、コンテンツのみをアプリケーションに返します。これが、DEALER が次のようなメッセージを送信する理由です。

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

というのは、REP はデリミタが削除されることを期待しており、DEALER が自動的にそれを行うわけではないからです。

ここで、REP がメッセージを DEALER に送り返すと、その逆が成り立ちます。アプリケーションでは、何も追加せずにデータを送信しているように見えます。

socket.send("world")

ただし、REP ソケットは前に区切り文字を追加して、メッセージが受信されたのと同じように「封筒に入れて」送信されるようにします。

では、なぜ DEALER は 2 回受け取る必要があるのでしょうか。

REP とは異なり、DEALER は区切り文字を暗黙的に処理しないためです。すべてをそのまま保持します。したがって、REP ソケットから受信していることがわかっているので、安全に2 回受信できます。1 つは区切り文字を自分で削除するため、もう 1 つは実際にデータを取得するためです。

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

ソース:

于 2013-05-22T14:30:22.690 に答える