Google协议缓冲区-缺少必需的字段,即使所有字段都明显存在
Google Protocol Buffers - Missing required fields even though all the fields are apparently present
我试图通过TCP发送协议缓冲区消息,但在接收端,我在尝试解析时遇到了"缺少必需字段"错误,尽管显然所有字段都在那里。我在包含消息长度的消息之前发送一个4字节的标头。
以下是消息定义:
message ReplayRequest {
required string channel = 1;
required uint32 start = 2;
required uint32 end = 3;
}
在客户端,我对标头进行编码,并将消息序列化为向量。
ReplayRequest req;
req.set_channel( "channel" )
req.set_start( 1 );
req.set_end( 5 );
int byte_size = req.ByteSize();
std::vector<uint8_t> write_buffer( HEADER_SIZE + byte_size );
encode_header( ... );
req.SerializeToArray( &write_buffer[HEADER_SIZE], byte_size );
这是结果缓冲区的十六进制打印,其中前4个字节是编码的消息长度(13个字节)。
00 00 00 0d 0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
在服务器端,我接收标头,对其进行解码,然后接收N个字节,其中N是标头中报告的消息大小。删除标头的服务器中的缓冲区为:
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
这与一个编码的客户端减去标头完全相同,但当我尝试ParseFromArray这个缓冲区时,我得到了一个错误:
libprotobuf ERROR c:umdf_runtimeprotobuf-2.4.1srcgoogleprotobufmessage_lit
e.cc:123] Can't parse message of type "ReplayRequest" because it is missing
required fields: channel, start, end
在调试时,我注意到解码失败的地方是protobuf生成的代码的这一部分:
bool ReplayRequest::IsInitialized() const {
if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false;
return true;
}
由于某种原因,服务器端的has_bits_被读取为零,但我不知道为什么。
有什么想法吗?
如果重要的话,我会使用boost::asio作为网络部分。
更新
根据请求,我发布了调用parseFromArray的代码。
request_.ParseFromArray( &data_buffer_, data_buffer_.size() );
request_是一个ReplayRequest成员变量,在此调用之前,对它没有任何操作
data_ buffer_是向量<uint8_t>其中TCP数据被接收到。
我确认它的大小正确,为13字节,这是它的十六进制转储,这与我在序列化后转储缓冲区客户端时得到的相同。
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
更新2
我能够在客户端将缓冲区解析为ReplayRequest的另一个实例,即:
...snip...
req.SerializeToArray( &write_buffer[HEADER_SIZE], byte_size );
ReplayRequest test;
test.ParseFromArray( &write_buffer[HEADER_SIZE], byte_size );
测试已成功填充正确的字段。
问题是您传入的是指向向量的指针,而不是指向向量数据的指针。
而不是request_.ParseFromArray( &data_buffer_, data_buffer_.size() );
尝试request_.ParseFromArray( &data_buffer_[0], data_buffer_.size() );
另一个解决方案,如果所需字段丢失但您不需要,并且您无法在protofile中将该字段更改为可选字段,则可以使用ParsePartialFromArray而不是ParseFromArray。
请参阅protobuf文档:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message_lite
- 将结构字段的类型展开为可变模板参数
- 将位字段导出到数组
- 为了方便起见,我应该避免公开私有字段变量吗
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 在java中读取c++字节的位字段
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 私有字段对象与私有继承?
- 声明没有默认构造函数的字段
- C++内存模型和位字段的最大序列
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 如何在QByteArray中放置和检索位字段而不会感到痛苦?
- Google协议缓冲区-缺少必需的字段,即使所有字段都明显存在
- 删除不存在的字段的子字段
- 如何检查结构的类型或字段是否存在
- 有条件地初始化一个结构体字段——仅当它存在于该结构体中时
- 如何检查类型中是否存在可能使用SFINAE的字段
- CDaoRecordset如果mfcc++中存在一个字段
- 如何检查桌面GUI应用程序中是否存在密码字段
- c++中的空字段和不存在的字段
- 用于检查字段是否存在的Sqlite查询失败