Кто-то упомянул возможность keepAlive TCP Socket.
Здесь это хорошо описано:
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
Я использую его следующим образом: после подключения сокета я вызываю эту функцию, которая устанавливает keepAlive. Параметр keepAliveTime
указывает время ожидания в миллисекундах без активности до отправки первого пакета keep-alive. Параметр keepAliveInterval
указывает интервал в миллисекундах между отправкой последовательных пакетов подтверждения активности, если подтверждение не получено.
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)time).CopyTo(inOptionValues, size);
BitConverter.GetBytes((uint)interval).CopyTo(inOptionValues, size * 2);
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
Я также использую синхронное чтение:
socket.BeginReceive(packet.dataBuffer, 0, 128,
SocketFlags.None, new AsyncCallback(OnDataReceived), packet);
А при обратном вызове здесь фиксируется тайм-аут SocketException
, который возникает, когда сокет не получает сигнал ACK после пакета keep-alive.
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = socket.EndReceive(asyn);
catch (SocketException ex)
{
SocketExceptionCaught(ex);
}
}
Таким образом, я могу безопасно обнаружить разрыв между TCP-клиентом и сервером.