web-dev-qa-db-ja.com

クラッシュしたプログラムから開いているソケットを閉じます

何千ものソケットを開いていますが、プログラムがクラッシュして、使用可能なソケットが大幅に少なくなることがあります。それらのぶら下がっているソケットをきれいにする方法はありますか?

2
Mahoni

ソケットは最終的にUnixカーネルによって閉じられます。クラッシュしたプログラムは、close()/shutdown()呼び出しのない通常のプログラム終了と同じです。

問題は、TCP/IPステートマシンのTIME_WAIT状態に関係している可能性があり、SO_REUSEADDRオプションを使用して解決する必要があります。これを確認する1つの方法は、クラッシュ後に再開する前に約5分間待つことです。十分なソケットが利用可能になっていることがわかった場合は、TIME_WAITロジックを調べて回避する必要があります。待機トリックで問題が解決しない場合は、プログラムに別の問題があり、それを特定する必要がある可能性があります。

これは、このテーマに関する良い読み物です。
TIME_WAITと、プロトコルおよびスケーラブルなクライアントサーバーシステムに対するその設計上の影響

参考のためにそこから2つの簡単な抜粋、

TIME_WAITは、2MSL待機状態とも呼ばれます。これは、TIME_WAITに移行するソケットが、最大セグメント寿命の2倍の期間そこにとどまるためです。 MSLは、すべての目的と目的で、TCPプロトコルの一部を形成するデータグラムが、破棄される前にネットワーク上で有効なままでいることができるセグメントの最大時間です。この制限時間は最終的には、TTLセグメントの送信に使用されるIPデータグラムのTCPフィールドによって制限されます。実装が異なれば、MSLに異なる値が選択され、一般的な値は30秒​​です。 、1分または2分。RFC793はMSLを2分として指定し、Windowsシステムはデフォルトでこの値に設定されますが、TcpTimedWaitDelayレジストリ設定を使用して調整できます。

(追記:したがって、4+1上記で提案された私のテストを待つ分)

2MSL遅延の変更は、通常、マシン全体の構成変更です。代わりに、SO_REUSEADDRソケットオプションを使用して、ソケットレベルでTIME_WAITを回避することを試みることができます。これにより、同じアドレスとポートを持つ既存のソケットがすでに存在しているときに、ソケットを作成できます。新しいソケットは基本的に古いソケットを乗っ取ります。 SO_REUSEADDRを使用すると、同じポートを持つソケットがすでにTIME_WAITにあるときにソケットを作成できますが、これにより、サービス拒否攻撃やデータ盗難などの問題が発生する可能性もあります。

この記事では、もう1つの方法について説明します。しかし、それは他の警告が伴います。

TCP接続を終了する別の方法があります。これは、接続を中止し、FINではなくRSTを送信することです。これは通常、SO_LINGERソケットオプションを0に設定することで実現されます。これにより、保留中のデータが保留中のデータが送信され、接続がFINで完全に閉じられるのではなく、破棄され、接続がRSTで中止されます。接続が中止されると、ピア間を流れる可能性のあるデータは次のようになることを理解することが重要です。破棄され、RSTはすぐに配信されます。通常は「接続がピアによってリセットされた」という事実を表すエラーとして送信されます。リモートピアは接続が中止されたことを認識し、どちらのピアもTIME_WAITに入りません。

これらのスキームを使用する前に、TCPマシンの動作を理解して、後でデバッグが必要になる他の状況を誤って導入しないようにすることをお勧めします。少なくともその記事を完全に読んでください:-)

3
nik