Question

I was implemented a simple request-reply architecture with a router using ZeroMQ. This works correctly for PyZMQ version 2.1.11. Unfortunately, when I test it on PyZMQ version 14.0.0, sender (REQ) can send to the router then router received its message and send to receiver (REP) but the receiver does not receive the message! I encounter to this problem when I upgraded PyZMQ from version 2.1.11 to 14.0.0.

REQ <-> ROUTER <-> REP

Here is my code:

sender.py

import zmq
import time

if __name__=='__main__':
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    socket.setsockopt(zmq.IDENTITY, "S")
    socket.connect("tcp://127.0.0.1:6660")
    i = 0
    while True:
        i += 1
        socket.send("R", zmq.SNDMORE)
        socket.send("", zmq.SNDMORE)
        socket.send("Message: %d" % i)
        print("Message : %d sent" % i)
        fromAddr = socket.recv()
        empty = socket.recv()
        resp = socket.recv()
        print("%s received!" % str(resp))
        time.sleep(1)

router.py

import zmq
import time

if __name__=='__main__':
    context = zmq.Context()
    frontend = context.socket(zmq.ROUTER)
    frontend.bind("tcp://*:6660")

    poll = zmq.Poller()
    poll.register(frontend, zmq.POLLIN)

    while True:
        sockets = dict(poll.poll(100))
        if frontend in sockets:
            if sockets[frontend] == zmq.POLLIN:
                fromAddr = frontend.recv()
                empty = frontend.recv()
                toAddr = frontend.recv()
                empty = frontend.recv()
                msg = frontend.recv()
                print("Message received from %s must be send to %s [%s]" % (str$
                frontend.send(toAddr, zmq.SNDMORE)
                frontend.send("", zmq.SNDMORE)
                frontend.send(fromAddr, zmq.SNDMORE)
                frontend.send("", zmq.SNDMORE)
                frontend.send(msg)
                print("Message has been send to %s!" % str(toAddr))

receiver.py

import zmq
import time

if __name__=='__main__':
    context = zmq.Context()
    socket = context.socket(zmq.REP)
    socket.setsockopt(zmq.IDENTITY, "R")
    socket.connect("tcp://127.0.0.1:6660")
    while True:
        print("Wating for request...")
        toAddr = socket.recv()
        empty = socket.recv()
        req = socket.recv()
        print("%s received!" % str(req))
        socket.send(toAddr, zmq.SNDMORE)
        socket.send(empty, zmq.SNDMORE)
        socket.send("Reply to %s" % str(req))

When I use this architecture:

routing with DEALER

The DEALER does not route to multiple receivers. DEALER only use round-robin method for sending messages to receivers. If ROUTER could be used instead of DEALER, then messages could be routed to specific receivers and will do round-robin between those.

Was it helpful?

Solution 2

According to what @nos said, ROUTER to REP is invalid combination but the ROUTER to ROUTER socket is valid one. Simply, I changed the REP socket to ROUTER! Revised code is here:

import zmq

if __name__=='__main__':
    context = zmq.Context()
    socket = context.socket(zmq.ROUTER)       # Changed
    socket.setsockopt(zmq.IDENTITY, "R1")
    socket.connect("tcp://127.0.0.1:6660")
    while True:
        print("Wating for request...")

        me = socket.recv()       # New
        empty = socket.recv()    # New
        toAddr = socket.recv()
        empty = socket.recv()
        req = socket.recv()
        print("%s received!" % str(req))

        socket.send(me, zmq.SNDMORE)       # New
        socket.send(empty, zmq.SNDMORE)    # New
        socket.send(toAddr, zmq.SNDMORE)
        socket.send(empty, zmq.SNDMORE)
        socket.send("Reply to %s" % str(req))

OTHER TIPS

A ROUTER to REP socket is an invalid combination as explained here: http://zguide.zeromq.org/page:all#Request-Reply-Combinations

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top