I have a server that receives connection requests from clients. This server makes use of the asynchronous Socket.BeginReceive
and Socket.EndReceive
method. The code is pretty similar to the code found here.
In my case, after calling Socket.BeginReceive
I need a timeout such that if the client hangs on to the connection but does not transmit any data at all for a fixed amount of time, I need to terminate the connection.
- How do I go about terminating the
connection in this scenario?
- What is the best way of coding a
timer?
Just call the socket's Close()
method. The callback method will run pretty quickly after that, you'll get an ObjectDisposedException
when you call the EndReceive()
method. Be prepared to catch that exception.
You probably don't want to block the thread that called BeginReceive
, you'll need a System.Threading.Timer
or System.Timers.Timer
to detect the timeout. Its callback should call Close()
. Beware of the inevitable race-condition this causes, the timer's callback will run if the response was received a microsecond before the timer expired. You'll close the socket, even though you got a good response. The next call to BeginReceive()
will fail immediately.
I know this thread is pretty old but I just encountered the same problem and I was not satisfied by the answer given here (or anywhere else by that matter).
A better solution to cancel a pending Socket.BeginReceive
is to call Socket.Shutdown
and not Socket.Close
. This way the asynch handler is raised "normally", and a call to Socket.EndReceive
returns 0 --> instead of throwing an ugly expected-exception.
You should always have an
if (Socket.EndReceive() > 0) {
//Do something
} else {
//Socket has been shut down (either by you or the other end of the connection)
//Now it's "safe" to call Socket.Close
Socket.Close();
}
so you don't even need to adjust your asynch-callback to handle the manual cancellation.
According to the MSDN article on Socket.BeginReceive it states
To cancel a pending BeginReceive, call the Close method.
You can Receive some initial data asynchronously and then make synchronous Receive for rest of the data and rely on ReceiveTimeout to disconnect the client. You can use Socket.Close to forcefully disconnect client.
But if you want to use async Receive only, then you can use timers and reset them on EndReceive. If it elapse you can disconnect the client forcefully.
But I think the first approach is better.