我正在编写一个使用protobuf作为序列化系统的轻量级服务器 - 客户端系统。我遇到了protobufs抱怨缺少必填字段的问题,但1)数据流中的字段明显存在,2)错误消息不识别丢失的字段。
首先是一些代码:
myMessages::DataRequest cData; // this is declared outside of the function in the global
// so it can be reused each time to avoid unnecessary
// memory allocation. Per the documentation in protobufs
.
.
.
bool processStream(u_int8_t *pStream, u_int32_t dwLength)
{
try
{
if (!cData.ParseFromArray(pStream, dwLength))
{
printf("Failed to parse data stream\n");
hexdump(pStream, dwLength);
return false;
}
}
catch(exception e)
{
printf("Exception in ParseFromArray: %s", e.what());
hexdump(pStream, dwLength);
return false;
}
这是我正在获取完整数据流并试图让protobufs对其进行解码的代码。大部分时间这都很好。但是通过这段代码进行了那么多迭代我得到了这个错误:
[libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type "myMessages.DataRequest" because it is missing required fields:
由于失败,我的代码吐出了这个显示给protobuf解析器的缓冲区:
Failed to parse data stream
000000: 08 86 ad 80 a5 f0 e7 aa e7 01 12 06 64 37 32 36 ............d726
000010: 31 37
DataRequest .proto非常简单......
message DataRequest {
required uint64 timeStamp = 1;
required string strid= 2;
optional bool checkin= 3;
// event messages
repeated internalMessage1 iEvents = 5;
repeated internalMessage2 oEvents = 6;
repeated internalMessage3 eEvents = 7;
repeated internalMessage4 qEvents = 8;
// aux messages
repeated auxMessages auxEvents = 20;
}
此proto表示唯一必需的字段是1和2(分别为timestamp和strid)。如同在hexdump中看到的那样解码数据的有线格式,您可以清楚地看到两个必需的字段都存在。此外,你可以看到重复的字段丢失了(所以它不像我在其中一个中缺少必填字段!)。
知道为什么protobufs在这里是一个混蛋?
谢谢!
tjac。
答案 0 :(得分:4)
事实证明,使用全局声明的变量,protobufs并不需要在多个线程中使用。我遇到的错误是我的服务器正在处理多个数据流的结果。我将上面的protobuf处理程序代码声明为每个线程调用的独立函数。由于没有排他性检查,因为我正处于一次调用(例如ParseFromArray)的中间,另一个线程的另一个调用可能是修改对象内的数据。
长话短说,我没有注意多线程编程的基本租户,因此我自己花了几个小时试图弄清楚protobufs是如何失败的。我希望将来能帮助别人。