peer.py
import zmq
import time
if __name__ == '__main__':
context = zmq.Context()
socket = context.socket(zmq.PUB)
while True:
print "I: Publishing"
socket.bind("tcp://*:5555")
socket.send_multipart(['general', 'Unique peer information'])
socket.unbind("tcp://*:5555")
time.sleep(1)
scanner.py
import zmq
if __name__ == '__main__':
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, 'general')
socket.connect("tcp://localhost:5555")
print "I: Scanning 5555"
while True:
message = socket.recv_multipart()
print "I: Receiving: {}".format(message)
I'm attempting to broadcast multiple peers over the same port, on the same computer and have a single "scanner" listen in and "see" who is available. Each peer would broadcast its contact information, a client would then use the scanner to find out who is available and then use the broadcasted information to connect via a REQ/REP channel.
To make this work, I've attempted to quickly bind a PUB socket, broadcast information about a peer, and then unbind so as to let other peers bind to the same socket, at a different time, and broadcast a different set of identifiers for the next peer.
I'm suspecting that messages get discarded before getting sent due to the unbinding (the same occurs with a call to close()) but I can't figure out how to get it to empty the queue prior to closing the connection so as to not discard any messages.
Any ideas?
I asked the same question on the ZMQ mailing-list and got some interesting replies, see here: http://lists.zeromq.org/pipermail/zeromq-dev/2014-June/026444.html
A subscriber has to connect to the publisher for it to receive any messages. The order of operations has to be something like the following:
PUB sockets are non-blocking, they won't wait until there's a subscriber to send to, it'll just move it through the queue, and if a subscriber isn't waiting for it, it'll discard it. Check out the pyzmq pub/sub examples, you'll see that the subscriber has to announce itself before the publisher can send a message and know it'll be received.
You can fake it with a timeout, if you know your subscriber will always be available within a specified period of time, otherwise pub/sub won't work for you.
So, what's happening is that your PUB socket binds, but it takes a non-zero amount of time for your subscriber to connect, even if you spun it up first, so it's not ready when you send your message. The message gets discarded, and then you spin everything down, still likely before the subscriber has a chance to connect completely.
You'll need to use a different kind of socket pair, perhaps rep/req, but you're looking for blocking behavior that will hold a message until the receiver is ready to receive it. This could mean using a central server that controls the information about which peers are available rather than attempting to broadcast the info to all peers, or something else depending on your messaging needs and architecture. Alternatively, you'll need a longer-lived pub/sub system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With