如何使用boost asio读取修复大小的数据包?

时间:2012-02-17 21:56:25

标签: c++ sockets boost boost-asio

我正在使用boost-asio进行同步读/写。数据以二进制格式出现,没有边界,长度信息以包格式编码。所以用指定的大小读入是很重要的。 ip::tcp::iostream能做到吗?有人能提供一个例子吗?感谢。

3 个答案:

答案 0 :(得分:1)

TCP是基于流的协议。这意味着无论你读什么都只是一个字节流。 让我们考虑一个例子:你有一个固定大小的消息,你通过TCP发送它。另一端的程序如何读取整个消息?有两种方法,一种是用控制字符围绕你的消息(例如开始时的STX和结束时的ETX)。在开始时,程序将在STX之前丢弃任何字符,然后将任何其他字符读入消息缓冲区,直到遇到ETX。

另一种方法是在固定大小的标题中编码消息长度(显然是你的情况)。因此,您可以做的最好的事情是找出一种方法来读取消息长度,解析它并相应地读取剩余的字节。

答案 1 :(得分: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

希望能帮到你!

答案 2 :(得分:1)

简单:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size));