TIME-WAIT 暗殺と SO_REUSEADDR の違いは何ですか
質問
SO_LINGER ソケット オプションを使用して、リンガー タイムをゼロに設定することで時間待機状態を意図的に「暗殺」することについて読んでいました。この本の著者は続けて、これを決して行うべきではなく、一般的には時間待機状態に決して干渉すべきではないと述べています。彼はすぐに、SO_REUSEADDR オプションを使用して時間待機状態をバイパスすることを推奨しています。
私の質問は、違いは何ですか?ということです。どちらの場合も、時間待機状態を途中で終了することになり、重複セグメントを受信するリスクを負うことになります。なぜ一方は良くてもう一方は悪いのでしょうか?
解決 2
さらに読んでみたところ、何が起こったのかについての私の理解は次のとおりです(正しいことを願っています)。
SO_REUSEADDR が設定されているソケットで close を呼び出すと (またはアプリがクラッシュすると)、次のシーケンスが発生します。
- TCP 送信バッファに残っているデータと FIN を送信します。
- close が呼び出された場合、残りのデータが正常に配信されたかどうかは示されずに、すぐに戻ります。
- データが送信された場合、ピアはデータ ACK を送信します
- ピアは FIN の ACK を送信し、自身の FIN パケットを送信します。
- ピアの FIN が確認され、ソケット リソースの割り当てが解除されます。
- ソケットは TIME-WAIT に入りません。
SO_LINGER 時間をゼロに設定してソケットを閉じると、次のようになります。
- TCP は送信バッファ内のデータをすべて破棄します
- TCP が RST パケットをピアに送信します
- ソケットリソースの割り当てが解除されます。
- ソケットが TIME-WAIT 状態にならない
したがって、リンガーをゼロに設定することはハックであり悪いスタイルであるという事実を超えて、接続の完全なシャットダウンを経ないためマナー違反でもあります。
他のヒント
TIME_WAITは絶対に正常です。これは、遠隔地からTCP FIN ACK続いてローカル側のTCP FIN後に生じます。 TIME_WAITであなただけのローカルアドレスに到達するための任意の浮遊パケットを待っています。紛失や浮遊パケットがあるしかしならば、TIME_WAITがそのTTLまたは「生存時間」を確保再びアドレスを使用する前に期限が切れます。
あなたは、あなたが基本的に言っているSO_REUSEADDRを使用する場合は、は、私は浮遊パケットが存在しないことを前提としています。これは近代的な、信頼性の高い、TCPネットワークと、ますます可能性があります。それはまだ可能ですが、それはほとんどありません。
ゼロにSO_LINGERを設定するとも呼ばれ、異常接近、開始するにはあなたの原因となる「接続シャットを非難します。」ここでは、TIME_WAITを尊重し、浮遊パケットの可能性について無視しないでください。
あなたがFIN_WAIT_1が表示された場合、リモートの場所があなたのFINに応じて、TCP FIN ACKを送信していないとして、これは、問題を引き起こす可能性があります。そこで、プロセスは、ネットワークのパーティションまたは不正なルートのいずれかに殺されたか、TCP FIN ACKが失われました。
あなたが問題を抱えているCLOSE_WAITを参照するとTCP FIN与えられたとき、あなたはTCP FIN ACKを送信していないとして、、ここであなたは接続をリークしている。
私はいくつかの他のプログラムが既に接続がオンに開く持っていたためにローカルポートに()バインドをワイルドカードにしてSO_REUSEADDRを使用しています。それは、この特定の使用は長い間何の二つのソケットが同時に同じアドレス/ポートコンボに()聞くしようとしないなどの問題を引き起こすことはありませんが判明します。