転載: https://blog.csdn.net/marywang56/article/details/76144275
TCP プロトコルでは、一方のパーティがアクティブにクローズして FIN_WAIT_2->TIME_WAIT に入ることが規定されており、CLOSED に入って TCP 制御ブロックを削除する前に、2MSL (MSL はメッセージ セグメントの最大生存時間) 待機する必要があります。2MSL 待機時間内に遅れて到着したメッセージ セグメントは破棄されます。
理由は 2 つあります。
TCP プロトコルの全二重接続を確実に閉じることができることを確認します
。クライアントが直接 CLOSED の場合、IP プロトコルの信頼性の低さまたはその他のネットワークの理由により、サーバーはクライアントによって最後に応答された ACK を受信しません。その後、サーバーはタイムアウト後も FIN を送信し続けます。この時点では、クライアントが CLOSED されているため、再送信された FIN に対応する接続が見つかりません。最終的に、サーバーは ACK の代わりに RST を受信し、サーバーは次のように考えます。接続エラーです。問題を上級管理者に報告してください。このような状況によってデータ損失が発生することはありませんが、TCP プロトコルが信頼性の高い接続の要件を満たさなくなります。したがって、クライアントは直接 CLOSED に入るのではなく、TIME_WAIT を維持し、再度 FIN を受信したときに、相手が ACK を受信したことを確認して、最終的に正しく接続を閉じることができます。
この接続の重複データ セグメントがネットワークから消えることを確認してください
。クライアントが直接 CLOSED してからサーバーへの新しい接続を開始した場合、この新しい接続のポート番号が閉じたばかりのポート番号と異なることは保証できません。つまり、新しい接続と古い接続のポート番号が同じである可能性があります。新しい接続と閉じられた古い接続のポート番号が同じであると仮定します。以前の接続からのデータがまだネットワークに残っている場合、これらの遅延データは、新しい接続が確立されるまでサーバーに到達しません。新しい接続と古い接続のポート番号は同じであり、TCP プロトコルはソケットのペアに基づいて異なる接続を決定するため、TCP プロトコルは遅延データが新しい接続に属するものと認識し、これが新しい接続と混同されます 。新しい接続の実際のデータ パケット。したがって、TCP 接続は TIME_WAIT 状態で 2MSL 待機する必要があり、これにより、この接続のすべてのデータがネットワークから確実に消えます。
一般的に、クライアントは積極的に接続を閉じ、すぐに接続を確立します。2MSL 以内では、以前接続されていたポート番号は使用できません。バインド関数を呼び出しても、-1 が返され (バインディング失敗)、カーネルが自動的に割り当てます。使用する新しいポート番号。したがって、サーバーが積極的に接続を閉じ、サーバーのポートが一般的に固定されている場合、データ パケットの混乱が発生するため、TCP では、積極的に接続を閉じる側は 2MSL 待つ必要があると規定しています。
この記事を参照してください。
記事の参照:
4 つの TCP 切断のうち、アクティブな終了側が接続を終了する前に 2MSL を待ったのはなぜですか? - Zhihu 出典: Zhihu、著者: Zeson
接続上のいずれかの当事者によって呼び出された後close()
、接続の両方の送信方向が閉じられ、それ以上データを送信できなくなります。一方の当事者が を呼び出した場合shutdown()
、接続は半クローズ状態になり、もう一方の当事者からデータを受信できます。
クライアント→サーバー方向のシャットダウンなど、半シャットダウンがある場合。その後、サーバーは引き続き送信でき、クライアントは引き続き受信できます。
このプロトコルでは、一方の当事者がアクティブにクローズし、FIN_WAIT_2
->を入力し、 TCP 制御ブロックにTIME_WAIT
入って削除する前に 2MSL (MSL は最大セグメント生存時間、LWIP は 1 分、Windows は 2 分) 待機する必要があると規定しています。CLOSED
2MSL 待機時間内に遅れて到着したメッセージ セグメントは破棄されます。
クライアント側でコネクションを閉じた後、すぐにコネクション(同じポート番号を使用)を確立した場合、2MSL以内は前のコネクションのポート番号は使用できず、関数を呼び出しても-1(バインディング失敗)となります。返されると、カーネルは自動的にbind
新しいポート番号を割り当てます。クライアントのポート番号は、使用できる限り気にしないため、通常はこれを気にしません。しかし、サーバーの場合は異なります。サーバーのポートは通常固定されています。クライアントは、接続を確立するためにサーバーのポート番号を知っている必要があります。したがって、サーバーが積極的に切断する場合は、注意を払うか、何らかの処理を行う必要があります。許可しない 使用可能になるまで 2MSL 待機します 具体的な方法は、有効化SO_REUSEPORT
(ローカル アドレスの再利用を許可) で、setsockopt
関数を呼び出すことで有効化できます。
MSL が待機する 2 つの理由: メッセージ セグメントには生存時間があり、接続が閉じられると、遅れたメッセージ セグメントが受信される可能性があります。このとき、すぐに新しい接続(同じポート)を確立すると、新しい接続は遅延メッセージを受信し、自分宛に送信されたものと誤って認識してしまいます。もう 1 つの理由は、全二重接続を確実に終了できるようにするためです。
FIN_WAIT_2
こちらから送信しFIN
、相手に了承された状態です。セミクローズを実装していない限り、相手側のアプリケーション層がファイルの終わりの指示を受信したことを認識し、逆方向の接続を閉じるための FIN を送信するのを待ちます。相手側のプロセスがこのシャットダウンを完了した場合にのみ、こちらの側は状態から状態にFIN_WAIT_2
入ります。TIME_WAIT
これは、こちら側が永久にこの状態に留まる可能性があることを意味します (FIN_WAIT_2
相手方が FIN パケットを送信しない場合)。もう一方の端もCLOSE_WAIT
状態になり、アプリケーション層がシャットダウンを決定するまで ( を呼び出してclose
から を入力するLAST_ACK
)、この状態を維持します。