C++ boost::asio::async_write send problems

2019-06-04 06:47发布

问题:

When I call async_write(), the remote peer is not receiving data until I call async_write() again. For example, I have 3 packets, a, b, and c:

SendPacket(a); // the remote side receives nothing
SendPacket(b); // the remote side receives packet a
SendPacket(c); // the remote side receives packet b

This is my code for sending:

void Session::SendPacket(packet p)
{
    dword len = p.Lenght(); 
    byte* buffer_send = new byte[len + 4]; //4 cause of the header

    memcpy(buffer_send + 4, p.GetRaw(), len); // copy everything to the buffer +4, 0-4 is header

    m_codec.EncodePacket(buffer_send, len);

    boost::asio::async_write(m_socket, boost::asio::buffer(buffer_send, len + 4),
                boost::bind(&Session::OnPacketSend, this, len + 4, boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred, buffer_send));

}

void Session::OnPacketSend(int len, const boost::system::error_code &e, size_t bytes_transferred, byte* buf)
{
    // this asynchronously fires when packet data is sent
    delete[] buf;
    if (e || bytes_transferred != len)
    {
        Stop();
        return;
    }
}

And I use it like this:

packet pp;

pp.WriteWord(0);
pp.WriteDword(4);
pp.WriteWord(0);

SendPacket(pp);

Also, when SendPacket() accepts packet by value instead of reference, a crash occurs.

Gr

回答1:

When small amounts of data are being written to a socket, such as in the original code (12 bytes~), one typically observes the behavior of data not being sent until subsequent data is written to the socket because of Nagle's algorithm. In short, many systems will attempt to mitigate IP/TCP congestion by concatenating small outbound messages into a single message that is then sent. To explicitly disable this behavior on a per-socket basis, set the boost::asio::ip::tcp::no_delay option:

boost::asio::ip::tcp::socket socket(io_service);
// ...
boost::asio::ip::tcp::no_delay option(true);
socket.set_option(option);

With sufficient bandwidth, disabling Nagle may result in higher throughput. Yet, it still may be worth examining the application protocol and logic much more to determine when or what data may be buffered, and when it needs to be immediately sent.