2012-07-05 11 views
5

これはどうやって行うのかという質問ではありませんが、私がやっていることが間違っているかどうかについての質問です。私は、タイマーや定期的に送られてきたメッセージなどを使わずに、データ(BeginReceive)を待っている間に、ソケットが予期せず閉じられたかどうかを検出することはできません。私はこれを行うために以下の設定を使用していましたが、これまでは完全に機能していました。予期しないソケット切断の検出

public void OnReceive(IAsyncResult result) 
{ 
    try 
    { 
     var bytesReceived = this.Socket.EndReceive(result); 

     if (bytesReceived <= 0) 
     { 
      // normal disconnect 
      return; 
     } 

     // ... 

     this.Socket.BeginReceive...; 
    } 
    catch // SocketException 
    { 
     // abnormal disconnect 
    } 
} 

私はそれが容易ではないことを読んだので、私の方法に何か問題があるかどうか疑問に思っています。ある?あるいは、プロセスを殺してケーブルを引っ張るなどの違いがありますか?

答えて

12

これは完全に可能です。

EndReceiveが0以外の値を返した場合、処理する着信データがあります。

EndReceiveがゼロを返す場合、リモートホストは接続の終了を閉じました。つまり、送信されたデータを受信できるようになっていれば、送信することができますが、それ以上の送信はできません。通常これが起きると、接続を終了して正常にシャットダウンを完了しますが、これは必須ではありません。

EndReceiveをスローすると、接続が異常終了しました(プロセスが停止し、ネットワークケーブルが切断され、電源が失われました)。

あなたがに注意を払わなければならないポイントのカップル:(あなたのコードでテストが誤解される)

  1. EndReceive

    未満ゼロを返すことはできません。
  2. これをスローすれば、SocketExceptionに加えて他の種類の例外をスローすることができます。
  3. ゼロを返す場合は、BeginReceiveの呼び出しを停止するように注意する必要があります。そうでなければ、BeginReceiveEndReceiveの間で無限で無意味なピンポンゲームを開始します(CPU使用率に表示されます)。あなたのコードはすでにこれを行っているので、何も変更する必要はありません。
+0

+1私はあなたが「そうするようにプログラムされているか」をどのように記述するのが好きだからです。 –

+2

+1また、それが再スローされない限り、すべてをキャッチするcatchステートメントを決して持つべきではないことを指摘したいと思います。 –

+1

@Alex私はあなたがそれらを転覆しない限り、すべての例外をキャッチすることの禁止に同意しない。 私はTCPサーバクラスを持っています。このクラスはここでのように非常によく動作します。サーバアプリケーション全体を終了させるためにいくつかのランダム例外を必要としません。 これは、すべての例外を捕捉し、OnExceptionCaughtイベントハンドラに渡す理由です。これは、いくつかのログ機能などに接続する必要があります。 – Algoman

関連する問題