我正在尝试编写一个处理程序类,该类订阅通过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;
}
答案 0 :(得分:1)
Poller
-instance + ZMQ_CONFLATE
对于预期的类用例没有上下文,原始设计似乎是一个相当的机械&#34;数据移动器的包装器,而不是任何MVP超薄设计,可以充分利用ZeroMQ可扩展形式通信原型信令/消息传递框架已经内置的优势。
更智能(以及更ZMQ_RCV_HWM
- 更安全(超出本主题的范围))并不总是机械地读取来自ZeroMQ Context
- 控制域的每条消息,除非真正需要从HandlerClass
的某个地方重新传输此类数据。
添加{strong> private
的Poller
实例,以便重新设计数据流机制 - 使用非破坏性查询,使用.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套接字传输中 - (几乎)免费 - 很酷,不是吗?