Search code examples
pythonsocketszeromqpollingpyzmq

Why is ZeroMQ poller not receiving messages (python)?


I'm trying to use the ZeroMQ Poller() functionality with two sockets in python:

import zmq

# Prepare our context and sockets
context = zmq.Context()

receiver = context.socket(zmq.DEALER)
receiver.connect("ipc:///tmp/interface-transducer")

subscriber = context.socket(zmq.SUB)
subscriber.bind("ipc:///tmp/fast-service")
subscriber.setsockopt(zmq.SUBSCRIBE, b"10001")

# Initialize poll set
poller = zmq.Poller()
poller.register(receiver, zmq.POLLIN)
poller.register(subscriber, zmq.POLLIN)

# Process messages from both sockets
while True:
    try:
        socks = dict(poller.poll())
    except KeyboardInterrupt:
        break

    if receiver in socks:
        message = receiver.recv()
        print("RECEIVER OK\n")

    if subscriber in socks:
        message = subscriber.recv()
        print("SUBSCRIBER OK\n")

And then the server that sends messages as a ROUTER is described as:

def main():
    context = zmq.Context()
    router = context.socket(zmq.ROUTER)
    router.bind("ipc:///tmp/interface-transducer")
    while True:
        identity = b'electrode-service'
        b_identity = identity
        router.send_multipart([b_identity, b'[1,2]'])
        print("Sent")
        time.sleep(1)

if __name__ == "__main__":
    main()

But when I run these two processes, it does not work as expected, the poller-script does not print anything. What could be the problem of such implementation?


Solution

  • Q : "What could be the problem of such implementation?"

    • such implementation is prone to deadlock & fails due to using exclusively the blocking-forms of .poll() & .recv() methods

    • such implementation is not self-defending enough in cases, where multiple peers get connected into AccessPoints, that implement round-robin incoming/outgoing traffic mappings

    • such implementation is awfully wrong in standing self-blinded in calling just a single .recv() in cases, where the .send_multipart() is strikingly warning, there will be multi-part message-handling needed

    • ipc:// Transport Class is prone to hide O/S related user-level code restrictions ( placed by the operating system on the format and length of a pathname and effective user-rights to R/W/X there )

    • ipc:// Transport Class .connect()-method's use is order-dependent for cases the target-address has not yet been created by O/S services ( a successful .bind() needs to happen first )

    • last but not least, any next attempt to .bind() onto the same ipc:// Transport Class target will silently destroy your intended ROUTER-access to the messaging/signalling-plane infrastructure & your implementation has spent zero-efforts to self-protect and self-diagnose errors that might silently appear "behind the curtains"

    Shouldn't zeromq deal automatically with deadlocks? I tried using the example given in the zeromq guide mspoller If I can't use .poll() and recv() simultaneously, how should I use ZMQ Poller structure? – hao123

    No,
    ZeroMQ zen-of-zero is performance + low-latency focused, so kindly consider all due care for blocking-prevention to be in your own hands (as needed & where needed, the core lib will never do a single more step than needed for the goal of achieving an almost linear scalable performance ).

    No,
    use freely both .poll()- & .recv()-methods, yet complete it so as to fit into a non-blocking fashion - .poll( 0 ) & add active detection + handling of multi-part messages ( again, best in a non-blocking fashion, using zmq.NOBLOCK option flag where appropriate ). Self-blocking gets code out of control.