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 disconnected ungracefully)?
11 Answers
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
-
I think you don't need to check the `Available` property. According to the `Poll` method's [MSDN page](http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.poll.aspx), it returns true also **if data is available for reading**. – Şafak Gür Nov 16 '12 at 10:26
-
3Read the documentation again, it also returns true if connection is closed or pending, so you don't know is it active unless you check if other side sent you some data. – zendar Nov 16 '12 at 15:01
-
8As a one-liner: `return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0)` – kasperhj Feb 06 '13 at 09:40
-
5This fails when you have yet connected the socket. If you do "Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);" And then MessageBox.Show(SocketConnected(s)); You will get True. See http://stackoverflow.com/a/14925438/741850 – Automatico Feb 17 '13 at 20:00
-
12According to `Poll` method's MSDN page: `This method cannot detect certain kinds of connection problems, such as a broken network cable, or that the remote host was shut down ungracefully. You must attempt to send or receive data to detect these kinds of errors.` – some_engineer Dec 21 '14 at 11:20
-
2This didn't work for me... When clients has been shut down ungracefully, part1=false and part2=true on Server Side, thus SocketConnected returns true. – dosuken123 Jul 04 '16 at 10:32
-
1Note that you need to drain all incoming data by Reading until Available == 0 before this will work, otherwise the data will sit in the buffer and the connection will look open. It's obvious once you've looked more closely at the code, but I didn't immediately pick up on it. – tekHedd Oct 19 '16 at 21:14
-
1Why does socket.connected even exist if its not 100% reliable – Sir Nov 18 '17 at 05:04
-
5Note that this is not thread safe! It can easily happen that another thread reads data between the s.Poll and s.Available, so s.Poll returns true, but then the buffer is emptied, causing part2 to also become true, and thus falsely assuming that the client has disconnected.. So you would need to wrap this code and every s.Receive in a lock {...} or similar - or what is the best approach here? – Wolfram Jan 28 '19 at 15:30
As zendar wrote, it is nice to use the Socket.Poll
and Socket.Available
, but you need to take into consideration that the socket might not have been initialized in the first place. This is the last (I believe) piece of information and it is supplied by the Socket.Connected
property. The revised version of the method would looks something like this:
static bool IsSocketConnected(Socket s)
{
return !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);
/* The long, but simpler-to-understand version:
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if ((part1 && part2 ) || !s.Connected)
return false;
else
return true;
*/
}

- 1
- 1

- 12,420
- 9
- 82
- 110
-
cool, I make a simple try and get ok, I will make more complex tests – fieldChao Jul 19 '19 at 03:03
-
Using DeMorgan law... return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0) && socket.Connected; – Latency Aug 06 '20 at 00:53
-
@Latency this might be correct, but it serves only to obscure the statement further, making it even harder for the reader to understand. The compiler will optimize it anyway, so the two statements are likely identical after compilation. – Automatico Aug 07 '20 at 14:50
-
@automatico the compiler doesn't optimize logic intended to be its converse. It may be easier to read by others, both tautologically equivilant. – Latency Aug 09 '20 at 01:05
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.

- 38,949
- 15
- 102
- 166
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.

- 2,287
- 1
- 26
- 32
-
I disconnect the socket by force (from a tool such as curr port), but there was no auto reconnect. – Eitan Jan 15 '17 at 12:24
-
2It won't auto-reconnect. It's just a "better" way to detect when a connection drops without sending any data. – toster-cx Jan 15 '17 at 16:30
-
3Using a combination of **KeepAlivesValues** with Zondar's suggestion (https://stackoverflow.com/a/2661876/378115) allowed me to detect even milliseconds intermitencies. – Julio Nobre Aug 05 '20 at 17:30
public static class SocketExtensions
{
private const int BytesPerLong = 4; // 32 / 8
private const int BitsPerByte = 8;
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1000, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException)
{
return false;
}
}
/// <summary>
/// Sets the keep-alive interval for the socket.
/// </summary>
/// <param name="socket">The socket.</param>
/// <param name="time">Time between two keep alive "pings".</param>
/// <param name="interval">Time between two keep alive "pings" when first one fails.</param>
/// <returns>If the keep alive infos were succefully modified.</returns>
public static bool SetKeepAlive(this Socket socket, ulong time, ulong interval)
{
try
{
// Array to hold input values.
var input = new[]
{
(time == 0 || interval == 0) ? 0UL : 1UL, // on or off
time,
interval
};
// Pack input into byte struct.
byte[] inValue = new byte[3 * BytesPerLong];
for (int i = 0; i < input.Length; i++)
{
inValue[i * BytesPerLong + 3] = (byte)(input[i] >> ((BytesPerLong - 1) * BitsPerByte) & 0xff);
inValue[i * BytesPerLong + 2] = (byte)(input[i] >> ((BytesPerLong - 2) * BitsPerByte) & 0xff);
inValue[i * BytesPerLong + 1] = (byte)(input[i] >> ((BytesPerLong - 3) * BitsPerByte) & 0xff);
inValue[i * BytesPerLong + 0] = (byte)(input[i] >> ((BytesPerLong - 4) * BitsPerByte) & 0xff);
}
// Create bytestruct for result (bytes pending on server socket).
byte[] outValue = BitConverter.GetBytes(0);
// Write SIO_VALS to Socket IOControl.
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.IOControl(IOControlCode.KeepAliveValues, inValue, outValue);
}
catch (SocketException)
{
return false;
}
return true;
}
}
- Copy the SocketExtensions class to your project
- Call the SetKeepAlive on your socket - socket.SetKeepAlive(1000, 2);
- Add a timer to check the IsConnected function

- 3,141
- 1
- 35
- 31
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;
}
}

- 8,521
- 5
- 40
- 64

- 1,795
- 1
- 22
- 22
-
2Looks like a good approach, but it doesn't work for me. If I just remove the network cable after a connection has been established, this method continues to return _true_ forever. – Rev May 15 '19 at 08:45
-
-
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.

- 3,833
- 3
- 13
- 32

- 330
- 3
- 15
-
-
this did work better at detecting the closed connection, but you have to be careful that your server will echo back the data that this sends in. When I did this, the data received in the next full transaction was polluted – hal9000 Nov 18 '20 at 23:28
Following the advice from NibblyPig and zendar, I came up with the code below, which works on every test I made. I ended up needing both the ping, and the poll. The ping will let me know if the cable has been disconnected, or the physical layer otherwise disrupted (router powered off, etc). But sometimes after reconnect I get a RST, the ping is ok, but the tcp state is not.
#region CHECKS THE SOCKET'S HEALTH
if (_tcpClient.Client.Connected)
{
//Do a ping test to see if the server is reachable
try
{
Ping pingTest = new Ping()
PingReply reply = pingTest.Send(ServeripAddress);
if (reply.Status != IPStatus.Success) ConnectionState = false;
} catch (PingException) { ConnectionState = false; }
//See if the tcp state is ok
if (_tcpClient.Client.Poll(5000, SelectMode.SelectRead) && (_tcpClient.Client.Available == 0))
{
ConnectionState = false;
}
}
}
else { ConnectionState = false; }
#endregion
The best way is simply to have your client send a PING every X seconds, and for the server to assume it is disconnected after not having received one for a while.
I encountered the same issue as you when using sockets, and this was the only way I could do it. The socket.connected property was never correct.
In the end though, I switched to using WCF because it was far more reliable than sockets.

- 51,118
- 72
- 200
- 356
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!

- 27
- 5
Use Socket.Connected
Property.
--UPDATE--
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. See 2

- 9,896
- 2
- 31
- 41
-
8Just note that even if Socket.Connected returns true, the socket might not be connected. If it is false, it's definitely not connected though. – nos Apr 18 '10 at 09:44