我正在测试使用zmq作为套接字和网络工具以及protobuf进行序列化的代码。
代码收到一个zmq_message并将其解析为protobuf类,作为回报,我更改了一个类成员的值,并将同一类发送回请求者。
在此过程中,以某种方式zmq断言check()
失败。我真的不知道为什么会这样,因为一切对我来说都很好。
代码在主文件中看起来像这样:
zmq::socket_t external(context, ZMQ_REP);
external.bind("tcp://*:29067");
zmq::message_t request;
external.recv(&request);
msg.deserialize(request);
msg.set_probed_value(12.0);
zmq::message_t response = msg.serialize();
external.send(response);
反序列化方法看起来像这样。
_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));
和序列化方法如下:
zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;
和 set_probed_value()
如下:
void set_probed_value(const double& val)
{
_msg.clear_probed();
_msg.set_probed(val);
}
我知道一个事实,就是当我将probed的值设置为与解析时设置的值不同的数字时,会引起问题。如果我删除该行msg.set_probed_value(12.0)
,则不会发生任何异常,并且一切正常。
断言失败:检查()(/apps/zmq/libzmq/src/msg.cpp:347)
答案 0 :(得分:1)
众所周知,所有消息处理都相当脆弱。
首先要进行显式的内容复制,而不是直接处理含糖的reinterpret_cast<...>( msg.data() )
内容(由ZeroMQ传递的指针引用)的直接语法怎么办?
使用
zmq_msg_copy()
复制邮件后,避免修改邮件内容 ,这样做会导致不确定的行为 >。如果您需要的是实际的硬拷贝,请使用zmq_msg_init_size()
分配新消息,并使用memcpy()
复制消息内容。
根据已发布的ZeroMQ API强烈建议,在完成安全内容复制之后,也建议使用close()
消息对象的显式request
。 >
从不直接访问
zmq_msg_t
成员,而始终使用zmq_msg
函数家族。
ZeroMQ API明确警告不要尝试以任何其他方式来操纵消息内容,而不是使用API发布的函数/方法。即使花费更多的代码和更多的SLOC-s,也最好避免使用任何此类技巧。
答案 1 :(得分:0)
您确定该zmq消息msg
中的NULL终止吗?
_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));
否则,这将使您的_msg
充满垃圾,因为它读到了您认为是字符串的结尾。
我问的原因是:
创建/发送邮件时,您不要包含NULL
zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;