2012-06-08 79 views
5

我正在使用Boost asio编写一个应用程序,其中客户端和服务器交换使用google proto缓冲区序列化的消息。我不知道通过网络发送的序列化消息的大小是多少。似乎原始buf对象没有任何分隔符。使用boost :: asio :: read_async读取Protobuf对象

以下是.proto文件的内容。

package tutorial; 

message Person { 
     required string name = 1; 
     required int32 id = 2; 
     optional string email = 3; 
} 

这里是如何,我从服务器

 tutorial::Person p; 
     p.set_name("abcd pqrs"); 
     p.set_id(123456); 
     p.set_email("[email protected]"); 
     write(p); 

     boost::asio::streambuf b; 
     std::ostream os(&b); 
     p.SerializeToOstream(&os); 
     boost::asio::async_write(socket_, b, 
         boost::bind(&Server::handle_write, this, 
           boost::asio::placeholders::error)); 

写在客户端,我阅读了上面使用boost ::支持ASIO :: async_read发送的消息。如何在下面的代码中找到arg的值作为参数boost::asio::transfer_at_least的参数?

boost::asio::async_read(socket_, response_, 
          boost::asio::transfer_at_least(arg), 
          boost::bind(&Client::handle_read_header, this, 
            boost::asio::placeholders::error)); 

否则我该如何确保boost :: async_read在读完整个对象后返回?

+0

我不知道答案,但我也很感兴趣,所以+1。 –

+0

你解决了你的问题吗?我对此非常感兴趣,而钢铁公司对于将protobuf + boost :: asio放在一起并没有明确的要求 –

回答

5

正确,protobufs不分隔。不知道消息从一个字节流到哪里终止 - 即使你已经看到了所有你知道的字段,也许有更多的重复元素,或者有人用一个你不知道的字段扩展了原型。

一个常见的解决方案是以长度为前缀的帧(通常编码为VarInt s)。例如,LevelDBSzl都使用这种方法。 A VarInt可以逐字节地被明确解码,然后在分析完整消息之前知道还有多少字节需要读取。

+2

参见http://stackoverflow.com/questions/2340730/are-there-c-eivaivalents-for-the-protocol -buffers-delimited-io-functions-in-ja一些API具有分隔的书写/阅读功能,您可以在答案中提到的方式轻松实现自己的功能。 – Andreas