'Boost async: which completion condition to use with async_read on a socket?

I'm using Boost's async_read method to read from a socket (see code below).

Wireshark shows that packets of various size are received on the socket port, some with size between 256B and 512B (we only focus on these packets below).

  • When I use transfer_all() completion condition, the handler function is never called, as if all packets were buffered forever and never actually read.

  • On the opposite, if I use for instance transfer_at_least(8) as a completion condition, the handler function is called twice per packet, once with 256B of data, then once with the remainder. This I can understand (I guess the condition is checked every 256B or something).

What I want is to have the handler called once for each packet with the full data, but I cannot find how to do this.

Note: this question (boost::asio::read with completion condition boost::asio::transfer_at_least(1) won't read until EOF) seems to say transfer_all is the way to go, but what is my issue here?


// Extract of .h file
class ClientSocket
{
    ...
    boost::asio::ip::tcp::socket socket_;
    boost::asio::streambuf input_buffer_;
    ...
}

// Extract of .cpp file
void ClientSocket::start_read()
{
    boost::asio::async_read(socket_, input_buffer_, boost::asio::transfer_at_least(8), boost::bind(&ClientSocket::handle_read, this, _1));
};

void ClientSocket::handle_read(const boost::system::error_code& ec)
{
    if (!ec)
    {
        const auto buffer = input_buffer_.data();
        std::size_t size = input_buffer_.size();
        // ---> the value of 'size' here show the issue
        
        // Copy data
        ...

        // Keep reading
        start_read();
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source