How to send byte message with ZeroMQ PUB / SUB setting?

4.1k views Asked by At

So I'm new to ZeroMQ and I am trying to send byte message with ZeroMQ, using a PUB / SUB setting.

Choice of programming language is not important for this question since I am using ZeroMQ for communication between multiple languages.

Here is my server code in python:

import zmq
import time

port = "5556"
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:%s" % port)
while True:
    socket.send(b'\x84\xa5Title\xa2hi\xa1y\xcb\x00\x00\x00\x00\x00\x00\x00\x00\xa1x\xcb@\x1c\x00\x00\x00\x00\x00\x00\xa4Data\x08')
    time.sleep(1)

and here is my client code in python:

import zmq

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5556")

total_value = 0
for update_nbr in range (5):
    string = socket.recv()
    print (string)

My client simply blocks at string = socket.recv().

I have done some study, so apparently, if I were to send string using PUB / SUB setting, I need to set some "topic filter" in order to make it work. But I am not sure how to do it if I were to send some byte message.

1

There are 1 answers

3
user3666197 On

ZeroMQ defines protocols, that guarantee cross-platform compatibility of both the behaviours and the message-content .

The root-cause:
to start receiving messages
one must change the initial "topic-filter" state for the SUB-socket
( which initially is "receive nothing" Zero-subscription )

ZeroMQ is a lovely set of tools, created around smart principles.

One of these says, do nothing on SUB-side, until .setsockopt( zmq.SUBSCRIBE, ... ) explicitly says, what to subscribe to, to start checking the incoming messages ( older zmq-fans remember the initial design, where PUB-side always distributes all messages down the road, towards each connected SUB-"radio-broadcast receivers", where upon each message receival the SUB-side performs "topic-filtering" on it's own. Newer versions of zmq reverse the architecture and perform PUB-side filtering ).

Anyway, the inital-state of the "topic-filter" makes sense. Who knows what ought be received a-priori? Nobody. So receive nothing.

Given you need or wish to start the job, an easy move to subscribe to anything ... let's any message get through.

Yes, that simple .setsockopt( zmq.SUBSCRIBE, "" )

If one needs some key-based processing and the messages are of a reasonable size ( no giga-BLOBs ) one may just simply prefix some key ( or a byte-field if more hacky ) in front of the message-string ( or a payload byte-field ).

Sure, one may save some fraction of the transport-layer overhead in case the zmq-filtering is performed on the PUB-side one ( not valid for the older API versions ), otherwise there is typically not big deal to subscribe to receive "anything" and check the messages for some pre-assembled context-key ( a prefix substring, a byte-field etc ) before the rest of the message payload is being processed.


The Best Next Step:

If your code strives to go into production state, not to remain as just an academia example, there will have to be much more work to be done, to provide surviveability measures for the hostile real-world production environments.

An absolutely great perspective for doing this and a good read for realistic designs with ZeroMQ is Pieter HINTJEN's book "Code Connected, Vol.1" ( may check my posts on ZeroMQ to find the book's direct pdf-link ).

Plus another good read comes from Martin SUSTRIK, the co-father of ZeroMQ, on low-level truths about the ZeroMQ implementation details & scale-ability