Improve ASIO TCP message separation
I just got started with Boost ASIO library, version 1.52.0. I am using TCP / SSL encryption with asynchronous sockets. From other questions asked here about ASIO, it seems that ASIO does not support receiving a variable length message and then passing the data for that message to the handler.
My guess is that ASIO puts data in a circular buffer and loses the entire track of every single message. If I missed something and ASIO gives you the ability to transmit individual messages, please let us know how.
My question is, if I can't somehow get just the bytes associated with an individual message, can I use transfer_exactly in async_read to get only the first 4 bytes, which in our protocol always put the length of the message. Then call either read or async_read (if reading won't work with asynchronous sockets) to read in the rest of the message? Will this work? Any better ways to do this?
source to share
I usually like to take the data I receive in async_read and put it in boost :: circle_buffer and then let my message parser layer decide when the message is complete and pull the data. http://www.boost.org/doc/libs/1_52_0/libs/circular_buffer/doc/circular_buffer.html
Partial code snippets below
boost::circular_buffer TCPSessionThread::m_CircularBuffer(BUFFSIZE);
void TCPSessionThread::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred)
{
// ignore aborts - they are a result of our actions like stopping
if (e == boost::asio::error::operation_aborted)
return;
if (e == boost::asio::error::eof)
{
m_SerialPort.close();
m_IoService.stop();
return;
}
// if there is not room in the circular buffer to hold the new data then warn of overflow error
if (m_CircularBuffer.reserve() < bytes)
{
ERROR_OCCURRED("Buffer Overflow");
m_CircularBuffer.clear();
}
// now place the new data in the circular buffer (overwrite old data if needed)
// note: that if data copying is too expensive you could read directly into
// the circular buffer with a little extra effor
m_CircularBuffer.insert(m_CircularBuffer.end(), pData, pData + bytes);
boost::shared_ptr<MessageParser> pParser = m_pParser.lock(); // lock the weak pointer
if ((pParser) && (bytes_transferred))
pParser->HandleInboundPacket(m_CircularBuffer); // takes a reference so that the parser can consume data from the circ buf
// start the next read
m_Socket.async_read_some(boost::asio::buffer(*m_pBuffer), boost::bind(&TCPSessionThread::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
source to share