2016-05-27 27 views
2

ソケットクライアント/サーバーをコーディングするとき、私はHeartBeatを実装してクライアントが生存しているかどうかを確認しましたが、他の方法でコードを探し出し、説明と同じように見えます。ソケットキープアライブ拡張機能はどのように機能しますか? C#

public static class SocketExtensions 
{ 
    /// <summary> 
    ///  A structure used by SetKeepAliveEx Method 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct TcpKeepAlive 
    { 
     internal uint onoff; 
     internal uint keepalivetime; 
     internal uint keepaliveinterval; 
    }; 

    /// <summary> 
    ///  Sets the Keep-Alive values for the current tcp connection 
    /// </summary> 
    /// <param name="socket">Current socket instance</param> 
    /// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param> 
    /// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param> 
    public static void SetKeepAliveEx(this Socket socket, uint keepAliveInterval, uint keepAliveTime) 
    { 
     var keepAlive = new TcpKeepAlive 
     { 
      onoff = 1, 
      keepaliveinterval = keepAliveInterval, 
      keepalivetime = keepAliveTime 
     }; 
     int size = Marshal.SizeOf(keepAlive); 
     IntPtr keepAlivePtr = Marshal.AllocHGlobal(size); 
     Marshal.StructureToPtr(keepAlive, keepAlivePtr, true); 
     var buffer = new byte[size]; 
     Marshal.Copy(keepAlivePtr, buffer, 0, size); 
     Marshal.FreeHGlobal(keepAlivePtr); 
     socket.IOControl(IOControlCode.KeepAliveValues, buffer, null); 
    } 
} 

HeartBeatを実装するよりはるかに簡単な方法で仕事をしているようですが、どうやって動作するのか分かりませんが、アンマネージドコードで何かをしているようです。もしそうなら、なぜですか?

説明ありがとう、ありがとう!

答えて

1

KeepAliveはTCPプロトコルの一部です。 KeepAliveを有効にすると、OSは空のパケットを定期的に相手に送信し、ACKを待ちます。要求されたタイムアウト時間内にACKが受信されない場合、接続は切断されたとみなされ、アプリケーションに通知することができる。

ただし、受信専用ソケットを使用している場合や、接続が長時間アイドル状態になる場合を除き、KeepAliveは通常必要ありません。

受信専用ソケットではデータを送信しないため、切断された接続を検出する唯一の方法は、ヌルパケットを送信してACKを待つことです。

OTOHに双方向ソケットがある場合は、相手にデータを送信するたびに、接続が切断されたかどうかも確認されますので、KeepAliveは不要です。データの送信側に応答してのみデータを送信する場合、プロトコルの「送信」部分に決して到達しない可能性があるため、KeepAliveが必要です。

また、Remy Lebeau氏のコメントで述べたように、長い間アイドル状態になる接続には、一部のルータ/ファイアウォールがしばらくしてアイドル状態の接続を閉じるため、KeepAliveが必要な場合があります。

+1

"*ただしKeepAliveは、受信専用ソケット*がある場合にのみ必要です。" - それは当てはまりません。キープアライブを使用する理由としては、長時間アイドル状態になっている間に接続を維持するなどの理由があります(データ接続で長時間の転送中にアイドル状態になっているFTPコマンド接続を考えてください)。ルータ/ファイアウォールの中には、しばらくしてアイドル状態の接続を閉じるものがあるため、Keepaliveを使用して対処することができます。 –

+0

@RemyLebeau:あなたはそうです、持ち上げてくれてありがとう。私は完全性のために私の答えを編集しました –

関連する問題