2012-03-30 26 views
1

私はC#でWindowsフォームアプリケーションを使っています。私は非同期の方法でサーバーに接続しているソケットクライアントを使用しています。接続が何らかの理由で壊れた場合、ソケットを直ちにサーバーに再接続しようとします。問題に近づくための最良のデザインはどれですか?接続が失われてもサーバーに再接続しようとしているかどうかを継続的に確認しているスレッドを作成する必要がありますか?ここでソケットクライアントを自動的に再接続する設計の選択

は、ソケット通信を処理している私のXcomClientクラスのコードです:

 public void StartConnecting() 
    { 
     socketClient.BeginConnect(this.remoteEP, new AsyncCallback(ConnectCallback), this.socketClient); 
    } 

    private void ConnectCallback(IAsyncResult ar) 
    { 
     try 
     { 
      // Retrieve the socket from the state object. 
      Socket client = (Socket)ar.AsyncState; 

      // Complete the connection. 
      client.EndConnect(ar); 

      // Signal that the connection has been made. 
      connectDone.Set(); 

      StartReceiving(); 

      NotifyClientStatusSubscribers(true); 
     } 
     catch(Exception e) 
     { 
      if (!this.socketClient.Connected) 
       StartConnecting(); 
      else 
      { 

      } 
     } 
    } 

    public void StartReceiving() 
    { 
     StateObject state = new StateObject(); 
     state.workSocket = this.socketClient; 
     socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(OnDataReceived), state); 
    } 

    private void OnDataReceived(IAsyncResult ar) 
    { 
     try 
     { 
      StateObject state = (StateObject)ar.AsyncState; 
      Socket client = state.workSocket; 

      // Read data from the remote device. 
      int iReadBytes = client.EndReceive(ar); 
      if (iReadBytes > 0) 
      { 
       byte[] bytesReceived = new byte[iReadBytes]; 
       Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes); 
       this.responseList.Enqueue(bytesReceived); 
       StartReceiving(); 
       receiveDone.Set(); 
      } 
      else 
      { 
       NotifyClientStatusSubscribers(false); 
      } 
     } 
     catch (SocketException e) 
     { 
      NotifyClientStatusSubscribers(false); 
     } 
    } 

今日は、受信したバイト数を確認するか、ソケット例外をキャッチすることにより、断線をキャッチしてみてください。

+0

どのクラスを使用するかによって異なります。ここであなたのコードを投稿するか、私たちにもっと情報を与えてください。 –

答えて

2

アプリケーションがソケット上のデータしか受信しない場合、ほとんどの場合、切断された接続は検出されません。長い間データを受信して​​いない場合、接続が壊れているかどうか、または相手側が単にデータを送信していないことが原因かどうかは分かりません。もちろん、これにもかかわらず通常の方法で相手側が閉じたコネクションを(ソケット上のEOFとして)検出します。

接続が切断されたことを検出するには、キープアライブが必要です。あなたはどちらかを行う必要があります。あなたはそれを得る、または、

  • ない場合は

    • は、それが設定したスケジュールに基づいてデータを送信すること他端保証を行い、あなたがタイムアウトし、接続を閉じプローブを送信もう一方の端にしばらくしている。この場合、OSは壊れた接続に気づいてくれます。壊れている場合は、すぐに(ピアによって接続がリセットされる)、結局は(接続がタイムアウトして)ソケットを読み取る際にエラーが発生します。

    いずれにしても、タイマーが必要です。イベントループ内のイベントとしてタイマーを実装するか、スリープするスレッドとして実装するかは、あなた次第であり、最良の解決策はおそらく残りのアプリケーションの構造に依存します。あなたがイベントループを実行するメインスレッドを持っているなら、おそらくそれにフックするのが最善でしょう。

    ソケットでTCPキープアライブオプションを有効にすることもできますが、アプリケーション層キープアライブは一般的により堅牢であると考えられます。

  • 関連する問題