1

I'm having troubles setting the no_delay option on an asio socket. The following code runs well, except for the delay. My server receives the messages only after the 5000 ms expire.

#include <boost/asio.hpp>
#include <boost/thread.hpp>
using namespace boost::asio;
struct Client
{
   io_service svc;
   ip::tcp::socket sock;

   Client() : svc(), sock(svc)
   {
       ip::tcp::resolver resolver(svc);
       ip::tcp::resolver::iterator endpoint = resolver.resolve(boost::asio::ip::tcp::resolver::query("127.0.0.1", "32323"));
       connect(sock, endpoint);
   }

   void send(std::string const& message) {
       sock.send(buffer(message));
   }
};

int main()
{
   Client client;

   client.send("hello world\n");
   client.send("bye world\n");

   boost::this_thread::sleep_for(boost::chrono::milliseconds(5000));
}

When trying to add a delay I have a few options:
1) Add the option before connection:

Client() : svc(), sock(svc)
{
   ip::tcp::resolver resolver(svc);
   ip::tcp::resolver::iterator endpoint = resolver.resolve(boost::asio::ip::tcp::resolver::query("127.0.0.1", "32323"));

   sock.set_option(ip::tcp::no_delay(true));
   connect(sock, endpoint);
}

However this throws set_option: Bad file descriptor

2) Add the option after the connection:

Client() : svc(), sock(svc)
{
   ip::tcp::resolver resolver(svc);
   ip::tcp::resolver::iterator endpoint = resolver.resolve(boost::asio::ip::tcp::resolver::query("127.0.0.1", "32323"));

   connect(sock, endpoint);
   sock.set_option(ip::tcp::no_delay(true));
}

However in this case, the option has no effect and I still see the delay. According to boost::asio with no_delay not possible? , I need to set the option after I've opened the socket but before I've connected the socket. So I've tried this:

Client() : svc(), sock(svc)
{
     ip::tcp::endpoint endpoint( ip::address::from_string("127.0.0.1"), 32323);
     sock.open(ip::tcp::v4());
     sock.set_option(ip::tcp::no_delay(true));
     sock.connect(endpoint);
}

However, I still see no effect. How can I set this option?

Edit: It's possible that I am not setting the option correctly on the server-side. This is the complete server code:

#include <boost/asio.hpp>
#include <iostream>

int main() {
    boost::asio::io_service        io_service;
    boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 32323));
    boost::asio::ip::tcp::socket   socket(io_service);

    acceptor.accept(socket);
    socket.set_option(boost::asio::ip::tcp::no_delay(true));

    boost::asio::streambuf sb;
    boost::system::error_code ec;
    while (boost::asio::read(socket, sb, ec)) {
        std::cout << "received:\n" << &sb;
    }
}
Community
  • 1
  • 1
Stewart
  • 4,356
  • 2
  • 27
  • 59
  • Does the server also have `no_delay` option set ? – Arunmu Nov 03 '16 at 10:19
  • Thanks for the response. I wasn't setting it on the server side. I think I am setting it now, but still don't see the effects. I've edited the original post to include the server code. – Stewart Nov 03 '16 at 10:48

1 Answers1

3

The client is properly setting the ip::tcp::no_delay option. However, the delay being observed is not the result of this option. Instead, it is the result of the server attempting to read more data than the client has sent, and when the client exits after sleeping 5000ms, the server's read operation completes with an error.

The read() operation initiated by the server will complete when either it has read streambuf.max_size() bytes or an error occurs. The streambuf's max size defaults to std::numeric_limits<std::size_t>::max() and can be configured in its constructor. In this case, the server attempts to read std::numeric_limits<std::size_t>::max() bytes, but the client only sends 22 bytes, sleeps 5000ms, then closes the socket. When the server observes that connection has closed, the read() operation completes with 22 bytes read and an error code of boost::asio::error::eof.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • This makes a lot of sense. I was just reading through [Boost's chat client example](http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/example/cpp03/chat/chat_client.cpp) and was trying to figure out why they sent the buffer size in the first byte of data. This explains it. Thanks for the info. – Stewart Nov 03 '16 at 20:05