Search code examples
c#socketsasynchronoustimeout

Timeout on asynchronous socket operation with SocketAsyncEventArgs


There seems to be no way to specify a timeout on the AcceptAsync() method of the .NET Socket class. It accepts a SocketAsyncEventArgs

if (!socket.AcceptAsync(awaitable.EventArgs))
   doasync();
else
   dosync();

Any suggestions on how to make this method timeout after a particular time frame? It seems to apply to the ReceiveAsync() method as well.

The Socket itself has some timeout values, like ReceiveTimeout, but the documentation indicates they do not apply to asynchronous methods.


Solution

  • ReceiveTimeout isn't as useful as many people think. Besides that it's only applicable to synchronous Receive() method calls, there is also that the socket is unusable after a timeout occurs. There is no way to have a receive operation timeout on a socket and then resume reading from the same socket.

    So the alternative that always works regardless of type of operation, turns out to be fine. Specifically:

    • Set a timer for the timeout period you want
    • Attempt the operation
    • If the operation completes before the timeout, disable the timer (or if completing an operation is to be immediately followed by another attempt at the operation, restart the timer)
    • If the operation does not complete before the timeout, close the socket.

    Closing the socket will cause any pending I/O operation to complete with an exception. Of course, having closed the socket, you won't be able to use that socket again. But that's how the underlying socket API works anyway, so that's not a problem.

    Note that your timer and the socket operation are racing. So it's important not only to implement the timer, but to synchronize the operation and the timer. E.g. use a volatile bool flag to signal that the operation completed successfully and that even if the timer handler is invoked, it should not close the socket.