Reputation: 448
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:
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.
Upvotes: 5
Views: 3468
Reputation: 448
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))
Upvotes: 3
Reputation: 229098
A ROUTER to REP socket is an invalid combination as explained here: http://zguide.zeromq.org/page:all#Request-Reply-Combinations
Upvotes: 3