特定のポートでサーバーと対話する小さなプログラムを作成しました。プログラムは正常に動作しますが:
プログラムが予期せず終了した後、そのソケット接続が状態に表示されて以来CLOSE_WAIT
。プログラムを実行しようとするとハングし、強制的に閉じる必要があり、ソケット接続がさらに蓄積されます。 CLOSE_WAIT
これらの接続をフラッシュする方法はありますか?
CLOSE_WAIT
プログラムがまだ実行中であり、ソケットが閉じられていないことを意味します (そして、カーネルは閉じられるのを待っています)。to を追加-p
しnetstat
て pid を取得し、それをより強力に (SIGKILL
必要に応じて) 強制終了します。CLOSE_WAIT
それはあなたのソケットを取り除くはずです。ps
pid を検索するために使用することもできます。
SO_REUSEADDR
サーバーとTIME_WAIT
ソケット用なので、ここでは適用されません。
クリスト・クラークの説明による。
CLOSE_WAIT は、接続のローカル側が相手側から FIN を受信したが、OS はローカル側のプログラムが実際に接続を閉じるのを待っていることを意味します。
問題は、ローカル マシンで実行されているプログラムがソケットを閉じていないことです。これは TCP チューニングの問題ではありません。プログラムが接続を開いたままにしている間、接続は (そしてまったく正しく) CLOSE_WAIT に永遠に留まることができます。
ローカル プログラムがソケットを閉じると、OS はリモート エンドに FIN を送信できます。これにより、FIN の ACK を待つ間、LAST_ACK に移行します。それが受信されると、接続は終了し、接続テーブルから削除されます (終了が CLOSE_WAIT の場合、TIME_WAIT 状態にはなりません)。
最新のTomcatサーバー(7.0.40)でも同じ問題が発生しています。数日間に一度反応しなくなります。
開いている接続を表示するには、次を使用できます。
sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT
この投稿で述べたように、 を使用/proc/sys/net/ipv4/tcp_keepalive_time
して値を表示できます。値は秒単位のようで、デフォルトは 7200 (つまり 2 時間) です。
それらを変更するには、編集する必要があります/etc/sysctl.conf
。
Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`
Socket
クライアント側とサーバー側の両方のインスタンスが明示的に呼び出す必要があることに注意してくださいclose()
。エンドの 1 つだけが呼び出さclose()
れた場合も、ソケットは CLOSE_WAIT 状態のままになります。
プログラムが新しいプロセスを生成する場合、そのプロセスは開いているすべてのハンドルを継承する可能性があることにも注意してください。独自のプログラムがクロスした後でも、これらの継承されたハンドルは、孤立した子プロセスを介してまだ生きている可能性があります。また、それらは netstat でまったく同じように表示されるとは限りません。しかし、それでも、この子プロセスが生きている間、ソケットは CLOSE_WAIT でハングアップします。
ADBを実行していたケースがありました。サーバープロセスがまだ実行されていない場合、ADB自体がサーバープロセスを生成します。これは最初にすべてのハンドルを継承しましたが、調査中にそれらのいずれかを所有しているとは表示されませんでした (macOS と Windows の両方に同じことが当てはまりました - Linux についてはわかりません)。