2012-02-17 41 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)); 
相关问题