2012-06-08 82 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