How to Check If a Socket Is Connected/Disconnected in C#

How to check if a socket is connected/disconnected in C#?

As Paul Turner answered Socket.Connected cannot be used in this situation. You need to poll connection every time to see if connection is still active. This is code I used:

bool SocketConnected(Socket s)
{
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if (part1 && part2)
return false;
else
return true;
}

It works like this:

  • s.Poll returns true if

    • connection is closed, reset, terminated or pending (meaning no active connection)
    • connection is active and there is data available for reading
  • s.Available returns number of bytes available for reading
  • if both are true:

    • there is no data available to read so connection is not active

How to detect a disconnected socket C#?

If the remote computer gracefully disconnects the session, the
Socket.Receive() method will return with 0 bytes. You must detect that
to know that the remote end has disconnected:

int recv = sock.Receive(data);
if (recv == 0)
{
// Remote client has disconnected.
}
else
{
// Remote client has sent data.
}

Also, even if there SocketException arises you can identify the exception for socket disconnection.

Hope this helps solve your problem.

How to detect a Socket Disconnect in C#

One option is to use TCP keep alive packets. You turn them on with a call to Socket.IOControl(). Only annoying bit is that it takes a byte array as input, so you have to convert your data to an array of bytes to pass in. Here's an example using a 10000ms keep alive with a 1000ms retry:

Socket socket; //Make a good socket before calling the rest of the code.
int size = sizeof(UInt32);
UInt32 on = 1;
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds.
UInt32 retryInterval = 1000; //If no response, resend every second.
byte[] inArray = new byte[size * 3];
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null);

Keep alive packets are sent only when you aren't sending other data, so every time you send data, the 10000ms timer is reset.

How can I check whether a (TCP) socket is (dis)connected in C#?

Death of a socket changes its behavior in several ways, so these methods are both valid :)

With both methods you actually check those parts of the socket's behavior that change after disconnection.

I don't really understand his statement about calling Receive() to make sure that the remote endpoint has actually received all the data I sent. (Do sockets block receiving until the sending buffer is empty?)

TCP is reliable protocol, that means that every packet you send must be acknowledged. Acknowledgement implies sending the packets with ACK bit set. These packets may or may not contain additional (payload) data.

When the socket is connected, Receive() will block until the socket receives a packet with non-empty payload. But when the socket is disconnected, Receive() will return as soon as the last ACK packet arrives.

Calling Receive() ensures that you either receive that last ACK packet from your remote endpoint or a disconnect timeout occurs and you will be able to receive nothing more on this socket.

The example on the same page shows how to do it. (I wonder why does it allocate a 1-byte array, even though it calls Send with 0 length?) But a post by Ian Griffiths says that I should read from the socket, not send through it.

When send()ing to a socket, you actually try to append some data to the end of the socket queue. Is there is some place left in the buffer, then your Send() returns instantly, if not, the Send() blocks until there is some place.

When the socket is in disconnected state, TCP/IP stack prevents all further operations with the buffer, that's why Send() returns an error.

Send() implements a basic pointer check, this means it fails when a NULL pointer is passed to it. You may probably pass any non-null constant as a pointer, but you better allocate 1 byte instead of making the constant up — just in case.


You may use any method you like, as none of them is resource consuming. As long as they are used for socket connection checking, they are identical.

As for me, I would prefer Receive(), as this is what you normally run in a cycle and wait for. You get a non-zero from Receive(), you process data; you get a zero, you process disconnection.

How Can I tell When a Socket has Disconnected

Detecting half-open connections is one of the classic socket programming scenarios. The Socket.Connected property is completely useless, and Socket.Poll does not work for every situation. It's best to actually send a "heartbeat" message every few seconds.

10054 is one of the common errors. It means the connection has been lost (not cleanly closed). It can be caused by the remote computer shutting down, the remote process exiting, or even an intermediate router being rebooted.

How to detect a Socket disconnection?

I ended up going with a heartbeat packet that requires an answer from the target. Basically, I send a predefined dummy packet and the target device must respond with the same, otherwise the connection is considered invalid.

Instantly detect client disconnection from server socket

Since there are no events available to signal when the socket is disconnected, you will have to poll it at a frequency that is acceptable to you.

Using this extension method, you can have a reliable method to detect if a socket is disconnected.

static class SocketExtensions
{
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}


Related Topics



Leave a reply



Submit