5

Both Linux and Windows support TCP keep-alive packets. They can be activated and configured with (system-dependent) setsockopt calls, see e.g. this article for the Linux case. When using boost::asio there appears to be support for keep-alive messages, see the current documentation. However that page only covers activating it. In several new responses to an older post it was pointed out that Boost has recently added the means to configure timeouts on operations (which obviates the need for setsockopt and #ifdef code-branches for different systems). However, a recent response still suggests calls on the native sockets.

My question is: How can I configure the time interval and timeouts of keep-alive packets using boost::asio?

Community
  • 1
  • 1
user8472
  • 3,268
  • 3
  • 35
  • 62
  • @KillianDS The post you quote deals with the `SO_RCVTIMEO` and `SO_SNDTIMEO` options. The current questions specifically deals with other constants. If you read the referenced article you'll find that the raw options on Linux systems are `TCP_KEEPIDLE` and `TCP_KEEPINTVL`. Furthermore, the accepted answer suggests to use raw sockets which I explicitly tried to avoid. – user8472 Feb 04 '14 at 14:14
  • no it doesn't, it takes a native handle, that is not the same as a raw socket. And while it might talk about different options than you want, the procedure is *exactly* the same (you even accepted a very similar answer here, that uses the same options). – KillianDS Feb 11 '14 at 08:13

1 Answers1

10

You can configure both the send timeout and receive timeout using the setsockopt options. Here is some platform-dependent code to do this on both windows and linux / unix, the example sets both send and receive timeouts to the same ten second value:

// start IO service    
io_context = new boost::asio::io_context;        

// define a tcp socket object    
tcpsocket = new boost::asio::ip::tcp::socket(*io_context); 

// the timeout value
unsigned int timeout_milli = 10000;

// platform-specific switch
#if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT
  // use windows-specific time
  int32_t timeout = timeout_milli;
  setsockopt(tcpsocket->native_handle(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
  setsockopt(tcpsocket->native_handle(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
#else
  // assume everything else is posix
  struct timeval tv;
  tv.tv_sec  = timeout_milli / 1000;
  tv.tv_usec = (timeout_milli % 1000) * 1000;
  setsockopt(tcpsocket->native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  setsockopt(tcpsocket->native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
#endif
Riot
  • 15,723
  • 4
  • 60
  • 67
  • 3
    So the answer is that `boost::asio` only allows activating it, but does not offer any way to configure it. I'll go with your solution, then. After all, it is not actually a problem to use native sockets. – user8472 Nov 25 '13 at 11:14
  • 2
    Indeed - I suppose the rationale is that not every implementation would allow the same configuration options, so asio chooses to leave potentially platform-specific configuration to the user. – Riot Nov 25 '13 at 14:20
  • @Riot have you seen the answers to http://stackoverflow.com/questions/292997/can-you-set-so-rcvtimeo-and-so-sndtimeo-socket-options-in-boost-asio? I was going to use a solution like yours, but apparently it doesn't work well with asio... – kenba Nov 25 '13 at 14:34
  • @kenba that top answer uses the same setsockopt solution here. I can confirm it works just fine with asio, i've been using this for a long time. The second answer there is nonsense, there's no need to inject anything into the asio namespace, just access the platform-dependent socket handles directly. That's all asio itself does behind the nice friendly wrapper, anyway. – Riot Nov 25 '13 at 18:00
  • Thanks @Riot it's the second one that I was worried about! I'm glad to hear that your solution's fine, I'll use it myself now. – kenba Nov 25 '13 at 18:13
  • 2
    Honestly this doesn't answer the OP's question. Keepalive values are set with SOL_TCP, {TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT} on posix and enabled with SOL_SOCKET, SO_KEEPALIVE – Climax Mar 17 '14 at 09:45
  • 2
    Actually, the OP's comment is "can you set ... socket options **in boost asio**? My answer is asio-specific; your comment just refers to posix. Boost asio also applies to non-posix systems. – Riot Mar 17 '14 at 10:07
  • This works but seems like it is not very reliable? If I switch off the wifi for example then my `boost::asio::async_read` never returns. – AdeleGoldberg Nov 04 '19 at 17:55
  • For keep-alive packets it seems that the accepted answer in https://stackoverflow.com/questions/23669005/tcp-keepalive-protocol-not-available describes the options to change (TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL for level IPPROTO_TCP instead of SOL_SOCKET). – Ian Gralinski Apr 01 '20 at 08:11