缓冲区最后收到ZeroMQ消息作为类成员

时间:2017-09-08 15:41:25

标签: c++ zeromq

我正在尝试编写一个处理程序类,该类订阅通过zeromq发布的消息并缓冲最后收到的消息。

我试过这样做如下。方法ReceivedMessage()将由循环调用函数中的包装器应用程序调用。一旦它返回true,我尝试使用GetReceivedMessageData()访问该消息。不幸的是,似乎数据未在成员zmq_receivedMessage_中正确保存。

我想这是因为zmq_receivedMessage_使用固定大小初始化而且zmq_subscriber_.recv(&zmq_receivedMessage_)调用不会自动调整大小?

最简单,最有效的方法是什么?我能想到的唯一方法是每次收到新邮件时都使用realloc()memcpy()。或者有更简单的方法吗?

#include <cstdint>
#include "zeromq_cpp/zmq.hpp"

class HandlerClass
{
public:
    /// @brief Initializes a AirSimToRos class instance.
    HandlerClass(std::string const& addr);

    // @brief Gets the message data received via ZeroMq as pointer.
    void* GetReceivedMessageData();

    // @brief Gets the message size received via ZeroMq as size_t.
    std::size_t GetReceivedMessageSize();

    // @brief Returns true if a new, full message was received via ZeroMq, false otherwise
    bool ReceivedMessage();

private:    
    /// @brief A ZeroMq context object encapsulating functionality dealing with the initialisation and termination.
    zmq::context_t zmq_context_;

    /// @brief A ZeroMq socket for subscribing to incoming messages.
    zmq::socket_t zmq_subscriber_;

    /// @brief A ZeroMq message that was received last. Might be empty if ReceivedMessage() never was true.
    zmq::message_t zmq_receivedMessage_; 

};

HandlerClass::HandlerClass(std::string const& addr)
    : zmq_context_(1)
    , zmq_subscriber_(zmq_context_, ZMQ_SUB)
{
    zmq_subscriber_.setsockopt(ZMQ_IDENTITY, "HandlerSubscriber", 5);
    zmq_subscriber_.setsockopt(ZMQ_SUBSCRIBE, "", 0);
    zmq_subscriber_.setsockopt(ZMQ_RCVTIMEO, 5000);
    zmq_subscriber_.connect(addr);
}

void* HandlerClass::GetReceivedMessageData()
{
    return zmq_receivedMessage_.data();
}

std::size_t HandlerClass::GetReceivedMessageSize()
{
    return zmq_receivedMessage_.size();
}

bool HandlerClass::ReceivedMessage()
{    
    int received_bytes = zmq_subscriber_.recv(&zmq_receivedMessage_);

    return received_bytes > 0;
}

1 个答案:

答案 0 :(得分:1)

一种方法是重新设计w / Poller -instance + ZMQ_CONFLATE

对于预期的类用例没有上下文,原始设计似乎是一个相当的机械&#34;数据移动器的包装器,而不是任何MVP超薄设计,可以充分利用ZeroMQ可扩展形式通信原型信令/消息传递框架已经内置的优势。

更智能(以及更ZMQ_RCV_HWM - 更安全(超出本主题的范围))并不总是机械地读取来自ZeroMQ Context - 控制域的每条消息,除非真正需要从HandlerClass的某个地方重新传输此类数据。

添加{strong> privatePoller实例,以便重新设计数据流机制 - 使用非破坏性查询,使用.poll() - 测试新消息到达的方法(还有一个实时/事件处理循环稳定性控制工具,不要等待特定集.poll() - 方法超时),同时又能推迟任何实际数据 - 尽可能晚地移动,直到数据确实需要流出HandlerClass - 实例之外,而不是之前的任何地方。

HandlerClass::HandlerClass(std::string const& addr)
    : zmq_context_(1)
    , zmq_subscriber_(zmq_context_, ZMQ_SUB)
{
    zmq_subscriber_.setsockopt( ZMQ_IDENTITY,   "HandlerSubscriber", 5 );
    zmq_subscriber_.connect(                     addr );
    zmq_subscriber_.setsockopt( ZMQ_SUBSCRIBE,  "", 0 );
    zmq_subscriber_.setsockopt( ZMQ_LINGER,      0 );  // ALWAYS, READY 4 .term()
    zmq_subscriber_.setsockopt( ZMQ_CONFLATE,    1 );  // SMART
    zmq_subscriber_.setsockopt( ZMQ_TOS,         T );  // WORTH DEPLOY & MANAGE
    zmq_subscriber_.setsockopt( ZMQ_RCVTIMEO, 5000 );
 // -------------------------------------------------  // ADD Poller-instance
    ...
 // -------------------------------------------------  // RTO
}

Nota Bene:如果还在ZeroMQ基础架构上进行了exgress流程,那么有一些省时的API工具可以将零拷贝消息重新编组到另一个ZeroMQ套接字传输中 - (几乎)免费 - 很酷,不是吗?