Question

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 ?

Was it helpful?

Solution

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.

OTHER TIPS

You can use the below method to find if a client is still connected. This

public static bool IsConnected(this TcpClient client)
{
    try
    {
        bool connected = !(client.Client.Poll(1, SelectMode.SelectRead) && client.Client.Available == 0);

        return connected;
    }
    catch
    {
        return false;
    }
}

This answer is for testing socket, which is how I got my code snippet.

Do you have control over the client? If so, cant you just have the client send a special packet to the server saying that it is disconnecting, and then disconnect the socket?

Are you trying to detect the case that the client has actually disconnected (using either Socket.Shutdown(), or Socket.Close()) or whether the client is idle for a huge amount of time, and therefore needs to be ejected?

In either case, have the client send a periodic message (just as you have done) to the server. The server can keep track of the last heartbeat, and if the client misses more than 3 heartbeats, you can disconnect the client. yes, it involves extra data, but that is not too bad in the grand scheme of things. If you tune it so that it sends the heartbeat at a good enough period, so that you get the advantage of knowing if the client is alive, and do not go too long between heartbeats, you could have a very good system.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top