C++ Google协议缓冲区-缺少必填字段,即使所有字段都明显存在

C++ Google协议缓冲区-缺少必填字段,即使所有字段都明显存在,c++,boost-asio,protocol-buffers,C++,Boost Asio,Protocol Buffers,我试图通过TCP发送一个协议缓冲区消息,但是在接收端,我在尝试解析时遇到了一个“缺少必填字段”错误,尽管显然所有字段都在那里。我在包含消息长度的消息之前发送一个4字节的头 以下是消息定义: message ReplayRequest { required string channel = 1; required uint32 start = 2; required uint32 end = 3; } 在客户端,我对头部进行编码,并将消息序列化为向量 ReplayRequest re

我试图通过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 );
在服务器端,我接收报头,对其进行解码,然后接收N个字节,其中N是报头中报告的消息大小。已删除标头的服务器中的缓冲区为:

0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
这与编码的客户端减去头部完全相同,但当我尝试解析此缓冲区时,我得到一个错误:

libprotobuf ERROR c:\umdf_runtime\protobuf-2.4.1\src\google\protobuf\message_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_uu是一个ReplayRequest成员变量,在调用之前对其不做任何操作

data_buffer_uu是接收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_u.ParseFromArray(&data_buffer,data_buffer_u.size())

试试

request_u.ParseFromArray(&data_buffer_0],data_buffer_u.size())

另一种解决方案如果缺少必需字段,但您不需要该字段,并且如果您无法在protofile中将该字段更改为可选字段,则可以使用ParsePartialFromArray而不是ParseFromArray

request_.ParseFromArray( &data_buffer_, data_buffer_.size() );

请参阅protobuf文档:

如果服务器说它没有任何必填字段,那么我想知道您是否在服务器上错误地提取和解析消息。您能发布调用ParseFromArray的代码吗?我注意到您的四字节编码邮件大小标题似乎是大端的。。。你在接收端把它解码成big-endian正确吗?我猜你一定是正确解码了,因为你得到了正确的N。@James头被正确解码了,你可以看到我打印的服务器缓冲区正好是13个字节的编码。你确定你没有在不同的程序之间使用不同的protos“编译”版本吗?当然,我会重新编译.PROTO文件到必要的C++文件,然后直接拷贝到两个项目中并重新构建。作为测试,您是否能够在第一个程序中对消息进行反序列化(使用不同的消息实例,而不是使用您序列化的同一实例)?@g19fanatic编译后的消息位于一个静态库中,该库从客户端和服务器链接,因此应该是同一个。我可以反序列化到另一个实例中,请检查问题的更新2。就这样。我以前在服务器上接收到一个缓冲区,所以&data\u buffer\u[HEADER\u SIZE]工作正常。分割缓冲区后,我移除了访问器。非常感谢。