2012-02-17 43 views
2

我正在做同步使用boost-asio進行讀取/寫入。數據以二進制格式進入,沒有邊界,長度信息以數據包格式編碼。所以以指定的大小閱讀是很重要的。 ip::tcp::iostream能做到嗎?有人可以提供一個例子嗎?謝謝。如何使用boost asio讀取修訂大小的數據包?

+0

你是什麼意思的信息:*長度信息的數據包格式編碼*?協議框架通常在應用程序級別完成,我認爲你通過考慮數據包而不是數據流來混淆自己。 – 2012-02-19 15:36:01

回答

1

我在一個程序上工作,它發送不同大小的數據。我用8字節的固定報頭進行編碼的大小,然後,我添加數據:

enum { header_length = 8 }; //const header length 

我得到的尺寸(m_outbound_data是爲std :: string ==序列化對象)

//give header length  
std::ostringstream header_stream 
header_stream << std::setw(header_length) //set a field padding for header 
       << std::hex     //set next val to hexadecimal 
       << m_data_out.m_outbound_data.size(); //write size in hexa 

m_data_out.m_outbound_header = header_stream.str(); //m_outbound_head == size in hexa in a std::string 

     //m_outbound_header = [ 8 byte size ] 
     //m_outbound_data = [ serialized data ] 

     //write all data in the std::vector and send it 
     std::vector<boost::asio::const_buffer> buffer; 
     buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_header)); 
     buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_data)); 

而閱讀,則需要在2時間看:1讀8個字節來獲取大小,然後在矢量讀取數據和反序列化到對象:

struct network_data_in { 
    char m_inbound_header[header_length]; //size of data to read 
    std::vector<char> m_inbound_data; // read data  
}; 

我用這個結構來獲取數據,在m_inbound_header上調用read來填充與尺寸第一緩衝區中,然後,在手柄:

//get size of data 
std::istringstream is(std::string(m_data_in.m_inbound_header, header_length)); 
std::size_t m_inbound_datasize = 0; 
is >> std::hex >> m_inbound_datasize; 
m_data_in.m_inbound_data.resize(m_inbound_datasize); //resize the vector 

然後調用再次讀取與緩衝的m_inbound_data,正好讀這個結果的數據發送 在你探微有反序列化數據的第二handle_read:

//extract data 
std::string archive_data (&(m_data_in.m_inbound_data[0]),m_data_in.m_inbound_data.size()); 
std::istringstream archive_stream(archive_data); 
boost::archive::text_iarchive archive(archive_stream); 
archive >> t; //deserialize 

希望對你有所幫助!

+0

+1好的答案,這是我的建議。修改您的協議以包含修復長度頭。如果你不能修改你的協議,請在問題中註明。 – 2012-02-19 15:36:54

1

TCP是基於流的協議。這意味着無論你讀什麼只是一個字節流。 我們來看一個例子:你有一個固定大小的消息,並通過TCP發送它。另一端的程序如何讀取整個消息?有兩種方法,一種是用控制字符包圍消息(例如,STX開始,ETX結束)。在開始時,程序會在STX之前丟棄任何字符,然後將任何其他字符讀入消息緩衝區,直到遇到ETX。

另一種方法是在一個固定大小的頭(這顯然是你的情況)中編碼消息長度。所以你可以做的最好的事情是找出讀取消息長度的方法,解析它並相應地讀取其餘的字節。

+1

我知道你需要長度信息,這是給定的。不清楚的是在API中指定這個長度(我想要讀取的字節數)。 – Oliver 2012-02-18 10:32:43

+0

@Oliver您的評論沒有意義。需要讀取的字節數在API中有詳細記錄['boost :: asio :: read'](http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/read/ overload1.html) – 2012-02-19 15:39:24

1

簡單:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size)); 
相關問題