问题
I have a C# TCP server application. I detect disconnections of TCP clients when they disconnect from server but how can I detect a cable unplug event? When I unplug the ethernet cable I can't detect the disconnection.
回答1:
You might want to apply "pinging" functionality, that will fail if there is TCP connection lose. Use this code to add extension method to Socket:
using System.Net.Sockets;
namespace Server.Sockets {
public static class SocketExtensions {
public static bool IsConnected(this Socket socket) {
try {
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
} catch(SocketException) {
return false;
}
}
}
}
Method will return false if there is no connection available. It should work to check if there is or no connection even if you had no SocketExceptions on Reveice / Send methods.
Bear in mind that if you had exception that had error message that is related to connection lose, then you don't need check for connection anymore.
This method is meant to be used when socket is looks like connected but might be not like in your case.
Usage:
if (!socket.IsConnected()) {
/* socket is disconnected */
}
回答2:
Try the NetworkAvailabilityChanged event.
回答3:
I found this method here. It checks the different states of the connection and signals a disconnect. But does not detect an unplugged cable. After a further search and trial and error this is how I solved it finally.
As the Socket
parameter I use on the server side the client socket from the accepted connection and on the client side the client that connected to the server.
public bool IsConnected(Socket socket)
{
try
{
// this checks whether the cable is still connected
// and the partner pc is reachable
Ping p = new Ping();
if (p.Send(this.PartnerName).Status != IPStatus.Success)
{
// you could also raise an event here to inform the user
Debug.WriteLine("Cable disconnected!");
return false;
}
// if the program on the other side went down at this point
// the client or server will know after the failed ping
if (!socket.Connected)
{
return false;
}
// this part would check whether the socket is readable it reliably
// detected if the client or server on the other connection site went offline
// I used this part before I tried the Ping, now it becomes obsolete
// return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
回答4:
This problem can also be resolved by setting the KeepAlive socket option like this:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.SetKeepAliveValues(new SocketExtensions.KeepAliveValues
{
Enabled = true,
KeepAliveTimeMilliseconds = 9000,
KeepAliveIntervalMilliseconds = 1000
});
These options can be tweaked to set how often checks are done to ensure the connection is valid. The sending of the Tcp KeepAlive will trigger the socket itself to detect the disconnect of the network cable.
来源:https://stackoverflow.com/questions/10298824/listening-for-an-ethernet-cable-unplugging-event-for-a-tcp-server-application