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?

+3


source to share


1 answer


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

      

+4


source







All Articles