2016-09-03 10 views
2

最近私はソケットプログラミングを研究し始め、個々のクライアントからの受信をうまく送信できる単純な非同期tcpサーバを作成しました。ここではそれのための単純化されたコードは次のとおりです。ネットワークストリームが切断を検出する方法

//accpet loop 

while (true) 
{ 
    var client = await listener.AcceptTcpClientAsync(); 
    new AppClient(client).Start(); 
} 

// and here is the start method in AppClient class 
public async void Start() 
{ 
     /// TcpClient is a class property which is in scope of this method 
     using (var stream = TcpClient.GetStream()) 
     { 
      string message = string.Empty; 
      byte[] buffer = new byte[1000]; 
      int bytesRead = 0; 
      while (true) 
      { 
       try 
       { 
        bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); 
       }   
       catch (Exception ex) 
       { 
         MessageBox.Show(ex.Message); 
         break; 
       } 

       // decode simple text message 
       message += Encoding.UTF8.GetString(buffer, 0, bytesRead); 


      } 
     } 
    } 

それは何私は動揺しますが、私はクライアントを破壊する方法に関係なく(プロセスを殺し、...)ということであるシングルスレッドな方法で接続の数千人を扱うが、 はReadAsyncメソッドは、すぐに私の考えと基本的に衝突する例外をスローします。 (私の知る限りでは、tcpの切断されたソケットの検出は簡単ではないはずです)

何か間違っていますか?

+2

あなたは本当に 'catch(Exception ex)'をしてはいけません。これはそのようなアンチパターンです。 – Enigmativity

+0

ありがとう、私はそれを覚えています。 – SHM

+0

彼がやっていることは、例外をキャッチすることで間違ったことは全くありません。 –

答えて

0

.ReadAsyncは、データの長さ==バッファの長さであれば、バッファに書き込みがある場合は読み込み可能なデータがあるかどうか常に取得しようとしているため、接続が切断されていることを「検出」していません関数を終了します。このすべてのステップ(おそらくもっとあります)は、にバインドされたStreamを含みます。次に、ソケットが(コードまたは手動で)閉じている場合、ストリームが閉じられます。閉じたストリームで何かをしようとすると例外がスローされます。

+0

Readasyncは、メソッドIDの残りの部分が実行されると、ソケットでデータを利用できるようになると一度だけ待ちます。 – SHM

1

cancellationTokenに.ReadAsync()を使用する必要があります。トークンの値をチェックするためにループを変更します。クライアントを殺すには、トークンに信号を送ります。

また、変数bytesReadもチェックしてください。 0と返す場合は、接続が閉じられました。

+0

キャンセルチップがありがとうございました。 bytesReadは決してゼロではありませんが、awaitを使ったReadAsyncメソッドは、btwを読み込むまではメソッドを一時停止します。 – SHM

+0

サーバ側の接続が切断された場合は0を返します。 –

1

ものを私は動揺になり、私はクライアント を破壊どんなに(プロセスを殺し、...)はReadAsync方法がすぐ

ネットワーク(ソケット)プログラミングへようこそ 例外をスローすることです。これらの例外では、これらのタイプのアプリケーションで例外に直面することが非常に普通であるため、自分自身を快適にする必要があります。この動作は仕様です。

例外のメッセージではなく、エンドユーザーが良好なメッセージを得るように開発する必要があるアプリケーションです。

... ReadAsyncメソッドはすぐに例外をスローし、 は基本的に自分の考えと衝突します。 (私の知る限りはそう簡単ではありません、TCPに 切断ソケットを検出読んで)

この理由は次のとおりです。

TcpClient.Connected Property /最後のIのようなクライアントソケットの接続状態を取得しますO操作。 falseを返すと、Clientソケットは接続されていないか、接続されていません。

接続プロパティは最新の操作時の接続状態のみを反映するため、メッセージの送受信を試みて現在の状態を判断してください。メッセージの送信が失敗した後、このプロパティはtrueを返しません。

この動作は仕様です。テストと送信/受信の間に接続が失われた可能性があるため、接続の状態を確実にテストすることはできません。あなたのコードでは、ソケットが接続されていると想定し、失敗した送信を正常に処理します。

+0

応答のおかげで、その無限ループでstream.ReadAsync()を待っていますか? (私はクライアントからの新しいデータを聞いていました) – SHM

+0

@SHM - はい、OKです。クライアントが事前に知られていない何度もデータを送信する場合は、待機してデータを受信し続ける必要があります。クライアントがソケットを閉じるとすぐにループが壊れ、例外がスローされます。 –

+0

@SHM - また、私の答えの最後の2つの段落を慎重に、そして辛抱強く読んでください。それらは非常に有益な言葉です。ネットワークプログラミングの経験を積んだGood Luck。 –

関連する問題