2016-06-30 9 views
0

私はサーバーと多数のクライアントを持っています。サーバーは、クライアントが接続を切断してこのクライアントに関連付けられた他の使い捨て可能なオブジェクトを持たないように、クライアントが非正常に切断されたとき(TCP FINを送信しない)を知る必要があります。ドロップされた接続の検出

とにかく、私はthisを読んで、リンクされたブログから「アプリケーションプロトコルへのキープアライブメッセージ」(ヘッダバイトのみを含む)と「最悪の場合を想定した明示的タイマー」を追加することに決めました。

クライアントが接続すると(btwはTcpListenerとTcpClientを使用しています)、サーバーは30秒をカウントするSystem.Threading.Timerを開始します。サーバーはそのクライアントから何かを受け取るたびに、タイマーをリセットします。タイマーが0になると、ユーザーを切断し、処分する必要があるものを廃棄します。また、クライアントアプリケーションにはタイマーがあり、ユーザーが15秒間何も送信しない場合(サーバーの値の半分、確かに)、キープアライブメッセージが送信されます。

私の質問は、これを達成するための簡単な方法はありますか?たぶんTcpClientのいくつかのオプション?私はTcpClient.ReceiveTimeoutで試しましたが、ReadAsyncで動作しないようです。

+0

Stephenが指摘するように、アプリケーションプロトコルでハートビートメッセージを使用することは、接続が有効であり、両方のアプリケーションが正しく動作していることを確認する唯一の確実な方法です。多くのエンジニアが、アプリケーションスレッドが失敗しても動作を続けるハートビートスレッドを作成したことに注意してください。ハートビートがソリューションの操作構造の一部を形成するようにする必要があります。その些細な問題はありません。 – Jim

+0

の非同期ソケット操作については、私は正常に使用したこのコードを参照していますhttp://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx私は 'SocketAwaitable' – Jim

+0

ありがとう!私はそのコードを試してみますが、「あなたはハートビートがソリューションの操作構造の一部を形成することを保証する必要があります」という意味を理解していませんでした。 – vlada

答えて

1

As Stephen points outアプリケーションプロトコルでハートビートメッセージを使用することは、接続が有効であり、両方のアプリケーションが正しく動作していることを確認する唯一の確実な方法です。多くのエンジニアが、アプリケーションスレッドが失敗しても動作を続けるハートビートスレッドを作成したことに注意してください。

クラスhereを使用すると、非同期ソケットの問題が解決します。

public sealed class SocketAwaitable : INotifyCompletion 
{ 
    private readonly static Action SENTINEL =() => { }; 

    internal bool m_wasCompleted; 
    internal Action m_continuation; 
    internal SocketAsyncEventArgs m_eventArgs; 

    public SocketAwaitable(SocketAsyncEventArgs eventArgs) 
    { 
     if (eventArgs == null) throw new ArgumentNullException("eventArgs"); 
     m_eventArgs = eventArgs; 
     eventArgs.Completed += delegate 
     { 
      var prev = m_continuation ?? Interlocked.CompareExchange(
       ref m_continuation, SENTINEL, null); 
      if (prev != null) prev(); 
     }; 
    } 

    internal void Reset() 
    { 
     m_wasCompleted = false; 
     m_continuation = null; 
    } 

    public SocketAwaitable GetAwaiter() { return this; } 

    public bool IsCompleted { get { return m_wasCompleted; } } 

    public void OnCompleted(Action continuation) 
    { 
     if (m_continuation == SENTINEL || 
      Interlocked.CompareExchange(
       ref m_continuation, continuation, null) == SENTINEL) 
     { 
      Task.Run(continuation); 
     } 
    } 

    public void GetResult() 
    { 
     if (m_eventArgs.SocketError != SocketError.Success) 
      throw new SocketException((int)m_eventArgs.SocketError); 
    } 
} 
関連する問題