web-dev-qa-db-ja.com

CLOSE_WAITソケット接続を削除する方法

私は特定のポートでサーバーと対話する小さなプログラムを書きました。プログラムは問題なく動作しますが、

プログラムが予期せず終了した後、そしてそのソケット接続はCLOSE_WAIT状態で表​​示されます。プログラムを実行しようとするとハングアップし、強制的に閉じる必要があります。これはmoreCLOSE_WAITソケット接続でさえも累積します。

これらの接続をフラッシュする方法はありますか?

74
Dilletante

CLOSE_WAITはあなたのプログラムがまだ実行中で、ソケットを閉じていないことを意味します(そしてカーネルはそれが行われるのを待っています)。 pidを取得するためにnetstat-pを追加してから、より強力に(必要に応じてSIGKILLを使用して)それを強制終了します。それはあなたのCLOSE_WAITソケットを取り除くでしょう。 pidを見つけるためにpsを使うこともできます。

SO_REUSEADDRはサーバーとTIME_WAITソケットのためのものなので、ここでは適用されません。

62
derobert

Crist Clark で説明されているように。

CLOSE_WAITは、接続のローカルエンドが相手側からFINを受信しましたが、OSはローカルエンドのプログラムが実際にその接続を閉じるのを待っていることを意味します。

問題は、ローカルマシンで実行されているプログラムがソケットを閉じていないことです。これはTCP調整の問題ではありません。プログラムが接続を開いたままにしている間、接続は(そしてまったく正しく)CLOSE_WAITに永遠にとどまることができます。

ローカルプログラムがソケットを閉じると、OSはリモートエンドにFINを送信して、FINのACKを待つ間にLAST_ACKに遷移します。それが受け取られれば、接続は終了し、接続テーブルから落ちます(あなたの端がCLOSE_WAITにあればあなたがするないTIME_WAIT状態に終わらない) 。

33
user2618402

CLOSE_WAIT接続が多すぎると、最初はコードに問題があることを意味しますが、これは受け入れられません。

あなたがチェックアウトすることをお勧めします: https://github.com/rghose/kill-close-wait-connections

このスクリプトが行うことは、接続が待っていたACKを送信することです。

これは私のために働いたものです。

7
mirage

最新のTomcatサーバー(7.0.40)でも同じ問題があります。それは数日の間1回無反応になります。

開いている接続を確認するには、次のようにします。

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`
6
Amil Waduwawara

クライアント側とサーバー側の両方のSocketインスタンスは、明示的にclose()を呼び出す必要があることに注意してください。どちらか一方の端だけがclose()を呼び出す場合も、ソケットはCLOSE_WAIT状態のままになります。

1
Binita Bharati