Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read a fix-sized packet using boost asio?

I am doing a synchronous read/write using boost-asio. The data is coming in binary format, without boundary, the length information is encoded in the packet format. So it is important to read in with specified size. Can ip::tcp::iostream do that? Can someone provide an example? Thanks.

like image 366
Oliver Avatar asked Oct 12 '25 09:10

Oliver


2 Answers

Simple:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size));
like image 60
vladon Avatar answered Oct 15 '25 01:10

vladon


I work on a program wich send different data with different size. I use a fixed header of 8 byte to encode the size, then, I add the data :

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

I get the size (m_outbound_data is a std::string == a serialized object)

//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));

And for reading, you need to read in 2 time : 1st read 8 byte to get the size, then read the data in a vector and deserialize into object :

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

I use this struct to get data, call read on the m_inbound_header to fill the buffer with size first, then, in the handle :

//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

then call again read with the m_inbound_data on buffer, this result of reading exactly the data sent In the second handle_read you juste have to deserialize the data :

//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

Hope that help you !

like image 27
blaize Avatar answered Oct 14 '25 23:10

blaize