4

私は、TCP 経由で通信する小さなプログラムをいくつか作成しました。あるプログラムがネットワーク接続を閉じたため、システムがハングするという無限の問題が発生し、他のエンドポイントは切断されたことに何らかの形で気付かない.

ある種の I/O 例外をスローするために閉じられた TCP 接続で I/O を実行することを期待していましたが、代わりに、プログラムがただハングしているように見え、他のエンドポイントが応答するのを永遠に待っています。明らかに、接続が閉じられている場合、その返信は決して来ません。(たとえば、20分間放置してもタイムアウトしないようです。)

ネットワーク接続を閉じたことをリモート エンドに強制的に「表示」させる方法はありますか?

更新:ここにいくつかのコードがあります...

public sealed class Client
{
  public void Connect(IPAddress target)
  {
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(ipAddress, 1177);
    _stream = new NetworkStream(socket);
  }

  public void Disconnect()
  {
    _stream.Close();
  }
}

public sealed class Server
{
  public void Listen()
  {
    var listener = new TcpListener(IPAddress.Any, 1177);
    listener.Start();
    var socket = listener.AcceptSocket();
    _stream = new NetworkStream(socket);
    ...
  }

  public void Disconnect()
  {
    socket.Shutdown(SocketShutdown.Both);
    socket.Disconnect(false);
  }
}
4

3 に答える 3

2

アプリケーションが正しい方法でソケットを閉じると、0 バイトを含むメッセージが送信されます。場合によっては、問題が発生したSocketExceptionことを示すメッセージが表示されることがあります。3 番目の状況では、リモート パーティが (ネットワーク ケーブルを抜くなどして) 接続されておらず、2 パーティ間で通信が行われていない場合です。

最後のことが起こった場合、リモートパーティに到達できなくなったことを検出するために、ソケットにデータを書き込む必要があります。これが、キープアライブ メカニズムが発明された理由です。キープアライブ メカニズムは、相手側とまだ通信できるかどうかを頻繁にチェックします。

あなたが今投稿したコードを見ると、操作を使用NetworkStreamするReadと、クライアントが接続を閉じたことを示すために0(バイト)の値が返されます。

ドキュメントには両方が記載されています

「読み取り可能なデータがない場合、Read メソッドは 0 を返します。」

「リモート ホストが接続をシャットダウンし、使用可能なすべてのデータが受信された場合、Read メソッドはすぐに完了し、0 バイトを返します。」

同じ段落で。実際NetworkStreamには、接続が開いている間に読み取りに使用できるデータがない場合はブロックされます。

于 2013-09-17T10:09:43.450 に答える