What do I need to do to get ZMQ_RADIO / ZMQ_DISH to work properly?

社会主义新天地 提交于 2019-12-06 05:25:41

The RADIO and DISH are in draft state and not available in stable build. If you need to access DRAFT API, build zmq from this link

The following is part of zmq.hpp

// These functions are DRAFT and disabled in stable releases, and subject to 
// change at ANY time until declared stable.                                 
    #ifdef ZMQ_BUILD_DRAFT_API

    //DRAFT Socket types.                                                       
#define ZMQ_SERVER 12
#define ZMQ_CLIENT 13
#define ZMQ_RADIO 14
#define ZMQ_DISH 15
#define ZMQ_GATHER 16
#define ZMQ_SCATTER 17
#define ZMQ_DGRAM 18
#endif

Houston, we have a problem:

I am not familiar with conditional builds and including draft-API(s) in recent ZeroMQ versions. If it were indeed intended to work your assumed way, the #define-s ought have been already solved there, haven't they?

Maybe you have digged from some GitHub source the correct #define ordinals for ZMQ_RADIO + ZMQ_DISH, compatible with core-functions, but a general approach to just manually:

#define                        A_NOT_IMPLEMENTED_CABLE_TV_BROADCAST_ARCHETYPE -1234
void   *dsh = zmq_socket( ctx, A_NOT_IMPLEMENTED_CABLE_TV_BROADCAST_ARCHETYPE );
assert( dsh              && "INF: a socket instantiation from [ctx] failed." );

        rc = bind( dsh, "udp://*:5555" );
assert( rc == 0          && "INF: a socket .bind( 'udp://*.5555' ) failed.");

sounds a lot suspicious, even with a promise of the flag ENABLE_DRAFTS=ON, doesn't it?


Summary

If your project aims at using RADIO/DISH, carefully review both the published API ( warnings about not-implemented / not-released features ), where you find also other mandatory steps:

Radio-dish is using groups (vs Pub-sub topics), Dish sockets can join a group and each message sent by Radio sockets belong to a group.

Groups are null terminated strings limited to 16 chars length (including null). The intention is to increase the length to 40 chars (including null).

Groups are matched using exact matching (vs prefix matching of PubSub).

ZMQ_RADIO side must use zmq_msg_set_group(3) to first assign a message to a group.

ZMQ_DISH side must use a call to zmq_join(3) so as to "enter" a group so as to receive any message, as by default there is, obviously, no membership upon it's instantiation.

ZMQ_DISH side may use a call to zmq_msg_group(3) to get the group the message actually belongs to.


ZeroMQ is in W.I.P. - so may like to check for similar services.

If in a need and hurry, Martin Sustrik has initiated another smart messaging/signalling tool - the .

After some troubles, the seems to have rolled out production release, where Scalable Formal Communication Patterns may help you in your Project goals. Worth a try.

Here is example of working with those two. I already tested it.

Most important thing you need to check that you don't load your system zmq library. In my case I did such thing in cmake:

set(ENABLE_DRAFTS ON)

add_subdirectory(libzmq)
set_target_properties(libzmq PROPERTIES PREFIX "dev-")

# If you want target
add_library(CppZeroMQ INTERFACE)

target_link_libraries(CppZeroMQ INTERFACE $<$<CONFIG:Debug>:libzmq>$<$<CONFIG:Release>:libzmq-static>)
# For CPP headers (you may install and change path here)
target_include_directories(CppZeroMQ INTERFACE my/path/to/cppzmq)
target_compile_definitions(CppZeroMQ INTERFACE ZMQ_BUILD_DRAFT_API=1)

Thanks to that it will distinguish between system lib and yours from source. Probably system library isn't using DRAFTS.


Server/Publisher part

    zmq::context_t context(1);
    zmq::socket_t publisher(context, ZMQ_RADIO);
    // We need set IP of destination, sad but true
    publisher.connect("udp://127.0.0.1:30666");

    std::string text;
    text.reserve(128);

    int number = 0;
    while(publisher.connected())
    {
        std::chrono::microseconds timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
            std::chrono::system_clock::now().time_since_epoch());

        text.clear();
        text += std::to_string(timestamp.count());
        text += ";";
        text += std::to_string(++number);

        zmq::message_t update{text.data(), text.size()};
        update.set_group("test");
        std::cout << "Sending: " << timestamp << " number:" << number << std::endl;
        publisher.send(update);
        std::this_thread::sleep_for(1s);
    }

Client/Subscriber part

    zmq::context_t context(1);
    zmq::socket_t subscriber(context, ZMQ_DISH);
    subscriber.bind("udp://*:30666");
    subscriber.join("test");

    int previousNumber = 0;
    int lostCount = -1;

    while(subscriber.connected())
    {
        zmq::message_t update;

        subscriber.recv(&update);

        std::string_view text(update.data<const char>(), update.size());
        std::cout << text;

        auto splitPoint = text.find(';');
        std::string serverTime = std::string{text.substr(0, splitPoint)};
        std::string serverNumber = std::string{text.substr(splitPoint + 1)};
        auto number = std::stoi(serverNumber);
        if(number != previousNumber + 1)
        {
            ++lostCount;
        }
        previousNumber = number;

        const auto diff =
            system_clock::now() -
            system_clock::time_point{std::chrono::microseconds{std::stoull(serverTime)}};

        // Beautify at: https://github.com/gelldur/common-cpp/blob/master/src/acme/beautify.h
        std::cout << " ping:" << Beautify::nice{diff} << "UDP lost: " << lostCount << std::endl;
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!