We have a use case with a tcp connection pool, where we want to do a quick check if a connection is still valid before re-using it.
We currently basically do it as follows (using the boost version of asio):
boost::asio::ip::tcp::socket & s = get_socket();
s.non_blocking(true);
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), s.message_peek);
s.non_blocking(false);
This nicely reports a connection that was closed by the peer, in which case we can reconnect. However, it uses a number of additional system calls to set the socket to non-blocking and back to blocking that could be eliminated on Linux, and maybe also on other OSes.
Linux supports MSG_DONTWAIT. It would be nice if asio could also support this flag, if it is available. Then we could do:
boost::asio::ip::tcp::socket & s = get_socket();
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), s.message_dontwait | s.message_peek);
This would eliminate the system calls to set the socket to blocking / non-blocking.
We have tried:
boost::asio::ip::tcp::socket & s = get_socket();
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), MSG_DONTWAIT | s.message_peek);
This however blocks the program. For example, the above code goes down to socket_ops::sync_recv, which has:
// Operation failed.
if ((state & user_set_non_blocking)
|| (ec != boost::asio::error::would_block
&& ec != boost::asio::error::try_again))
return 0;
But for MSG_DONTWAIT to work, sync_recv would need:
// Operation failed.
if ((state & user_set_non_blocking)
|| (flags & MSG_DONTWAIT)
|| (ec != boost::asio::error::would_block
&& ec != boost::asio::error::try_again))
return 0;
With this patch, the receive call with MSG_DONTWAIT works as expected. In socket_ops.ipp, more functions similar to sync_recv could add support MSG_DONTWAIT in this way.
It would be nice to be able to use MSG_DONTWAIT with the asio API. If necessary we can go more low-level through s.native_handle().