web-dev-qa-db-ja.com

TcpClient接続を適切かつ完全に閉じる/リセットする方法は?

TcpClient接続を閉じるまたはリセットする正しい方法は何ですか?ハードウェアと通信するソフトウェアがありますが、時々何かがおかしくなり、ソフトウェアを再起動するまで通信できなくなります。

TcpClient.Close()を強制し、nullに設定しようとしましたが、うまくいきません。ソフトウェアの完全な再起動のみが機能します。

提案?


TpcClientは1つの場所でのみ定義されていますが、ライブラリ全体で使用されているため、usingキーワードは使用できません。 (また、常に1つの接続のみが存在します)

これは、通信を処理するライブラリです。ソフトウェア自体は、コントローラクラス(ハードウェアを表す)のResetConnection()メソッドを呼び出すことができます。

現在のように見えます

if (tcpClient != null)
{
    tcpClient.Close();
    tcpClient = null;
}

ここで読んだことから、「= null」の代わりにtcpClient.Dispose()を使用する必要があります。

それを試して、それが違いを生むかどうかを確認します。

67
TimothyP

接続を閉じる前にストリームを閉じる必要があります。

tcpClient.GetStream().Close();
tcpClient.Close();

クライアントを閉じても、ストリームは閉じられません。

78

受け入れられた答えは時代遅れであり、これに関する他の答えには何も見られないので、私は新しいものを作成しています。 .Net 2以前では、接続を閉じる前に手動でストリームを閉じる必要がありました。このバグは、C#のTcpClientの以降のすべてのバージョンで修正されており、 Closeメソッド のドキュメントに記載されているように、メソッドCloseの呼び出しは接続とストリーム

Microsoft Docsに従って編集

Closeメソッドは、インスタンスを破棄済みとしてマークし、関連付けられたSocketがTCP接続を閉じることを要求します。LingerStateプロパティに基づいて、TCP接続は開いたままになることがありますCloseメソッドが呼び出された後、データの送信がまだ残っている場合、基礎となる接続のクローズが完了したときに通知は提供されません。

このメソッドを呼び出すと、最終的には関連付けられたSocketが閉じられ、データが作成された場合はデータの送受信に使用されるNetworkStreamも閉じられます。

21
John Demetriou

Wordを使用: using プログラミングの良い習慣。

using (TcpClient tcpClient = new TcpClient())
{
     //operations
     tcpClient.Close();
}
20
Michał Ziober

ソケット接続を閉じて、ソケットの再利用を許可します。

tcpClient.Client.Disconnect(false);
7
Justin Tanner

ソケットを閉じて再度開くことができる正しい方法は次のとおりです。

tcpClient.Client.Disconnect(true);

ブールパラメータは、ソケットを再利用するかどうかを示します。

Disconnect method usage

4
Kevin Gigiano

一部の内部ロギングを除き、Close == Dispose。

破棄はtcpClient.Client.Shutdown(SocketShutdown.Both)を呼び出しますが、エラーはすべて処理されます。直接呼び出すと、役に立つ例外情報を取得できる場合があります。

4
jyoung

適切なusingステートメントがすべてあるにもかかわらず、Closeを呼び出し、指数関数的なバックオフロジックを使用してTcpClientを再作成しますが、アプリケーションが=を回復できない問題がまだあります。 TCPアプリケーションを再起動せずに接続します。System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote Host

しかし、LingerStateにオプションTcpClientがあり、問題を解決した可能性があります(私自身のハードウェアのセットアップが失敗することが多いため、数か月間はわからないかもしれません!)。 [〜#〜] msdn [〜#〜] を参照してください。

// This discards any pending data and Winsock resets the connection.
LingerOption lingerOption = new LingerOption(true, 0);

using (var tcpClient = new TcpClient 
       {SendTimeout = 2000, ReceiveTimeout = 2000, LingerState = lingerOption })
   ...
3
Ian Mercer

TcpClient.Dispose() を明示的に呼び出してみましたか?

TcpClient.Close()およびTcpClient.Dispose()-ed[〜#〜] all [〜#〜]接続があることを確認してください?

0
chakrit