How can you check if a network socket (System.Net.Sockets.Socket) is still connected if the other host doesn\'t send you a packet when it disconnects (e.g. because it discon
I made an extension method based on this MSDN article. This is how you can determine whether a socket is still connected.
public static bool IsConnected(this Socket client)
{
bool blockingState = client.Blocking;
try
{
byte[] tmp = new byte[1];
client.Blocking = false;
client.Send(tmp, 0, 0);
return true;
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
{
return true;
}
else
{
return false;
}
}
finally
{
client.Blocking = blockingState;
}
}
The accepted answer doesn't seem to work if you unplug the network cable. Or the server crashes. Or your router crashes. Or if you forget to pay your internet bill. Set the TCP keep-alive options for better reliability.
public static class SocketExtensions
{
public static void SetSocketKeepAliveValues(this Socket instance, int KeepAliveTime, int KeepAliveInterval)
{
//KeepAliveTime: default value is 2hr
//KeepAliveInterval: default value is 1s and Detect 5 times
//the native structure
//struct tcp_keepalive {
//ULONG onoff;
//ULONG keepalivetime;
//ULONG keepaliveinterval;
//};
int size = Marshal.SizeOf(new uint());
byte[] inOptionValues = new byte[size * 3]; // 4 * 3 = 12
bool OnOff = true;
BitConverter.GetBytes((uint)(OnOff ? 1 : 0)).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)KeepAliveTime).CopyTo(inOptionValues, size);
BitConverter.GetBytes((uint)KeepAliveInterval).CopyTo(inOptionValues, size * 2);
instance.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
}
// ...
Socket sock;
sock.SetSocketKeepAliveValues(2000, 1000);
The time value sets the timeout since data was last sent. Then it attempts to send and receive a keep-alive packet. If it fails it retries 10 times (number hardcoded since Vista AFAIK) in the interval specified before deciding the connection is dead.
So the above values would result in 2+10*1 = 12 second detection. After that any read / wrtie / poll operations should fail on the socket.
The Socket.Connected property will tell you whether a socket thinks it's connected. It actually reflects the status of the last send/receive operation performed on the socket.
If the socket has been closed by your own actions (disposing the socket, calling methods to disconnect), Socket.Connected
will return false
. If the socket has been disconnected by other means, the property will return true
until you next attempt to send or recieve information, at which point either a SocketException
or ObjectDisposedException
will be thrown.
You can check the property after the exception has occurred, but it's not reliable before.
As Alexander Logger pointed out in zendars answer, you have to send something to be completely sure. In case your connected partner does not read on this socket at all, you can use the following code.
bool SocketConnected(Socket s)
{
// Exit if socket is null
if (s == null)
return false;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if (part1 && part2)
return false;
else
{
try
{
int sentBytesCount = s.Send(new byte[1], 1, 0);
return sentBytesCount == 1;
}
catch
{
return false;
}
}
}
But even then it might take a few seconds until a broken network cable or something similar is detected.
Just use the KeepAlive like @toster-cx says and then use the Socket Connected status to check if the Socket is still connected. Set your receive timeout at the same timeout of the keepalive. If you have more questions i am always happy to help!