誰かがTCPソケットのキープアライブ機能について言及しました。ここでそれはうまく説明されています:
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
私はそれをこのように使用しています:ソケットが接続された後、私はこの関数を呼び出して、keepAliveをオンに設定します。このkeepAliveTime
パラメーターは、最初のキープアライブパケットが送信されるまでアクティビティがないタイムアウトをミリ秒単位で指定します。この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)keepAliveTime).CopyTo(inOptionValues, size);
BitConverter.GetBytes((uint)keepAliveInterval).CopyTo(inOptionValues, size * 2);
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
非同期読み取りも使用しています:
socket.BeginReceive(packet.dataBuffer, 0, 128,
SocketFlags.None, new AsyncCallback(OnDataReceived), packet);
そして、コールバックでは、ここでキャッチタイムアウトSocketException
が発生します。これは、キープアライブパケットの後にソケットがACK信号を取得しない場合に発生します。
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = socket.EndReceive(asyn);
}
catch (SocketException ex)
{
SocketExceptionCaught(ex);
}
}
このようにして、TCPクライアントとサーバー間の切断を安全に検出できます。