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
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 !
Simple:
boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size));
TCP is a stream-based protocol. This means that whatever you read is just a stream of bytes. Let's consider an example: you have a message of a fixed size and you send it over TCP. How can the program at the other end read the entire message? there are two ways, one is to surround you message with control chracters (e.g. STX at start and ETX at end). At the start, the program would discard any chars before STX, then read any other chars into the message buffer until ETX is encountered.
Another way is to encode the message length in a fixed-size header (which apparently is your case). So the best thing you can do is figure out a way to read the message length, parse it and read the remaining bytes accordingly.