I'm developing a server in C# which can accept only one client and I need to know when this client is disconnected to be able to accept another connection requests.
I'm using a first Socket which continuously listen to connection request with Socket.BeginAccept
and accept or reject clients. When a client is accepted, the new Socket which is returned by Socket.EndAccept
is used for the communication between client and server. Then, the server waits for commands from the client with Socket.Begin/EndReceive
and sends responses. The server uses a Telnet-like protocol, which means that each command and each line of response must end with \r\n
.
To detect if the client has been disconnected, I've installed a timer which sends every 500ms an empty message ("\r\n
") to the client. If the client is disconnected, an exception is thrown by the Socket. This exception is caught by the server which closes the current session and accepts new connection. This solution is robust but implies unneeded traffic over the network and must be handled correctly by the client which must filter dummy messages before getting an actual response.
I've tried to send an empty buffer (Socket.Send(new byte[1], 0, 0)
), but it seems that doesn't work in the direction server->client.
Another solution might be to handle the case where Socket.EndReceive
returns 0 byte. It works fine for the case of a disconnection which occurs during "idle" time. But if the client disconnects during a message transfert, the server doesn't always see it and waits indefinitely.
I've already seen several threads and questions about this problem, but I've never seen any good solution.
So my question is: what is the best way to detect a disconnection in .Net ?
The only other option is if it is TCP is to have TCP send a keep-alive every so often, which is still polling such as what you're doing now but handled at the TCP layer so you're protocol doesn't need to know.
There's no way around the polling however since without sending something to the other client and getting a response you have no way to know whether it's still connected or not.
Keep alive may also be required anyway when communicating through stateful packet inspection such as standard NAPT to avoid having the remote server drop the session due to in-activity.