Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my C++ ZeroMQ subscriber not receive any data?

Tags:

c++

python

zeromq

My (Python) publisher:

import zmq
import time

context = zmq.Context()
socket = context.socket(zmq.PUB)
connectStr = "tcp://*:%d" % 5563
socket.bind(connectStr)

messageNum = 0
while True:
    ++messageNum
    message = "Testing %d"%messageNum
    print("Sending.. '%s'"%message)
    socket.send_string(message)
    time.sleep(1)
    messageNum += 1

My (C++) subscriber (running in GTest):

TEST(ZeroMqPubSubTest, SubscribeGetsData)
{

    // Set up the subscriber we'll use to receive the message.
    zmq::context_t context;
    zmq::socket_t subscriber(context, ZMQ_SUB);
    // Connect to the publisher
    subscriber.connect("tcp://127.0.0.1:5563");
    subscriber.setsockopt(ZMQ_SUBSCRIBE, ""); // Set the filter blank so we receive everything

    zmq::message_t response(0);
    EXPECT_TRUE(subscriber.recv(&response));
}

I start up the publisher then start up the subscriber. The latter never returns though.

If I run a Python subscriber doing (I thought) exactly the same thing..

import zmq

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect ("tcp://127.0.0.1:5563")
socket.setsockopt_string(zmq.SUBSCRIBE, "")

print ("Waiting for data...")
while True:
    message = socket.recv()
    print ("Got some data:",message)

..it works fine:

Waiting for data...

Got some data: b'Testing 8'

Got some data: b'Testing 9'

like image 235
Jon Cage Avatar asked Feb 01 '26 14:02

Jon Cage


1 Answers

There are two overloads of setsockopt defined in zmq.hpp:

 template<typename T> void setsockopt(int option_, T const& optval)
 {
     setsockopt(option_, &optval, sizeof(T) );
 }

 inline void setsockopt (int option_, const void *optval_, size_t optvallen_)
 {
     int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
     if (rc != 0)
         throw error_t ();
 }

By providing only two arguments you implicity used the first overload, which assumes a value length of sizeof(T). This resolves to one, because "" is a zero-terminated character array. To pass in an empty string you need to use the second overload and specify a length of 0:

subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);

Alternatively, use a zero size data type:

char none[0];
subscriber.setsockopt(ZMQ_SUBSCRIBE, none);
like image 158
MB-F Avatar answered Feb 03 '26 03:02

MB-F