Alguien mencionó la capacidad keepAlive de TCP Socket. Aquí está muy bien descrito:
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
Lo estoy usando de esta manera: después de que el socket está conectado, llamo a esta función, que activa keepAlive. El keepAliveTime
parámetro especifica el tiempo de espera, en milisegundos, sin actividad hasta que se envía el primer paquete Keep-Alive. El keepAliveInterval
parámetro especifica el intervalo, en milisegundos, entre el momento en que se envían paquetes de mantenimiento de vida sucesivos si no se recibe ningún reconocimiento.
void SetKeepAlive(bool on, uint keepAliveTime, uint keepAliveInterval)
{
int size = Marshal.SizeOf(new uint());
var inOptionValues = new byte[size * 3];
BitConverter.GetBytes((uint)(on ? 1 : 0)).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)keepAliveTime).CopyTo(inOptionValues, size);
BitConverter.GetBytes((uint)keepAliveInterval).CopyTo(inOptionValues, size * 2);
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
También estoy usando lectura asincrónica:
socket.BeginReceive(packet.dataBuffer, 0, 128,
SocketFlags.None, new AsyncCallback(OnDataReceived), packet);
Y en la devolución de llamada, aquí se captura el tiempo de espera SocketException
, que aumenta cuando el socket no recibe la señal ACK después del paquete de mantenimiento.
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = socket.EndReceive(asyn);
}
catch (SocketException ex)
{
SocketExceptionCaught(ex);
}
}
De esta manera, puedo detectar de forma segura la desconexión entre el cliente TCP y el servidor.