著者:小林コーディング
グラフィックコンピュータ財団(オペレーティングシステム、コンピュータネットワーク、コンピュータ構成、データベースなど) ウェブサイト:https ://xiaolincoding.com
皆さんこんにちは、シャオリンです。
TCP の 3 ウェイ ハンドシェイクと 4 ウェイ ハンドシェイクの特定のステップでパケットが失われるとどうなるかについての記事を書きました。
当時は文字での説明が中心で覚えにくいかもしれませんので、各工程の異常事態を絵で描き直して、みんなが理解して覚えられるようにしました。
さあ行こう!
TCP スリーウェイ ハンドシェイクのパケット損失
最初の握手が失われました。どうなりますか?
クライアントがサーバーとの TCP 接続を確立したい場合、最初に送信するのは SYN メッセージであり、次にSYN_SENT
state。
その後、クライアントがサーバーからの SYN-ACK メッセージの受信に失敗した場合 (2 回目のハンドシェイク)、「タイムアウト再送信」メカニズムをトリガーして SYN メッセージを再送信し、再送信された SYN メッセージのシリアル番号は同じです。
オペレーティング システムのバージョンによって、1 秒のタイムアウトと 3 秒のタイムアウトが異なる場合があります。このタイムアウトは、カーネルにハードコードされています。変更する場合は、カーネルを再コンパイルする必要があり、面倒です。
クライアントが 1 秒後にサーバーから SYN-ACK メッセージを受信しない場合、クライアントは SYN メッセージを再送信しますが、何回再送信されますか?
Linux では、クライアントの SYN メッセージの再送信の最大回数は、カスタマイズ可能なtcp_syn_retries
カーネル、デフォルト値は通常 5 です。
# cat /proc/sys/net/ipv4/tcp_syn_retries
5
通常、1 回目のタイムアウト再送は 1 秒後、2 回目のタイムアウト再送は 2 秒後、3 回目のタイムアウト再送は 4 秒後、4 回目のタイムアウト再送は 8 秒後、2 回目のタイムアウト再送は 8 秒後です。 16 秒のタイムアウトで再送信した後。そうです、各タイムアウトには前のタイムアウトの 2 倍の時間がかかります。
5 回目のオーバータイム再送信の後、サーバーは 32 秒間待機し続けます. それでもサーバーが ACK で応答しない場合、クライアントは SYN パケットを送信しなくなり、TCP 接続を切断します.
したがって、合計の所要時間は 1+2+4+8+16+32=63 秒、約 1 分です。
たとえば、tcp_syn_retries のパラメーター値が 3 であるとすると、クライアントの SYN メッセージがネットワークで常に失われると、次のプロセスが発生します。
特定のプロセス:
- クライアントが SYN メッセージを 3 回オーバータイムで再送信すると、tcp_syn_retries が 3 であるため、再送信の最大回数に達しているため、サーバーがまだ受信に失敗する場合は、しばらく待ちます (時間は前回のタイムアウトの 2 倍の時間です)。 2 番目のハンドシェイク (SYN-ACK メッセージ) の後、クライアントは切断されます。
2 回目の握手が失われました。
サーバーがクライアントから最初のハンドシェイクを受信すると、クライアントに SYN-ACK メッセージを返します. これが 2 回目のハンドシェイクであり、サーバーはこの時点でSYN_RCVD
状態に
2 番目のハンドシェイクSYN-ACK
メッセージに実際には 2 つの目的があります。
- 2 番目のハンドシェイクの ACK は、最初のハンドシェイクの確認メッセージです。
- 2 番目のハンドシェイクの SYN は、TCP 接続を確立するためにサーバーによって開始されるメッセージです。
したがって、2 回目の握手が失われた場合、さらに興味深いことが起こります。
2 回目のハンドシェイク メッセージには、クライアントへの 1 回目のハンドシェイクの ACK 確認メッセージが含まれているため、クライアントが 2 回目のハンドシェイクを長期間受信していない場合、クライアントは自身の SYN メッセージ (最初のハンドシェイク) が失われたと見なします。クライアントはタイムアウト再送信メカニズムをトリガーし、SYN メッセージを再送信します。
次に、2 番目のハンドシェイクにはサーバーの SYN メッセージが含まれているため、クライアントがそれを受信すると、ACK 確認メッセージをサーバーに送信する必要があり (3 番目のハンドシェイク)、サーバーは SYN メッセージがクライアントによって受信されたと見なします。終了させて頂きました。
次に、2 番目のハンドシェイクが失われると、サーバーは 3 番目のハンドシェイクを受信しないため、サーバーはタイムアウト再送信メカニズムをトリガーして SYN-ACK メッセージを再送信します。
Linux では、SYN-ACK パケットの再送信の最大回数はtcp_synack_retries
カーネル、デフォルト値は 5 です。
# cat /proc/sys/net/ipv4/tcp_synack_retries
5
したがって、2 番目のハンドシェイクが失われると、クライアントとサーバーの両方が再送信します。
- クライアントは、最初のハンドシェイクである SYN メッセージを再送信します。再送信の最大回数は、
tcp_syn_retries
カーネル。 - サーバーは、2 回目のハンドシェイクである SYN-ACK メッセージを再送信します。再送信の最大回数は、
tcp_synack_retries
カーネル。
たとえば、tcp_syn_retries のパラメータ値が 1 で、tcp_synack_retries のパラメータ値が 2 の場合、2 回目のハンドシェイクが常に失われる場合、発生するプロセスは次のようになります。
特定のプロセス:
- クライアントが SYN メッセージを 1 回以上再送信すると、tcp_syn_retries が 1 であるため再送信の最大回数に達しているため、それでも SYN を受信できない場合は、しばらく待ちます (時間は前回のタイムアウト時間の 2 倍です)。サーバーからのメッセージ 2 番目のハンドシェイク (SYN-ACK メッセージ) の後、クライアントは切断されます。
- サーバーが SYN-ACK メッセージを 2 回オーバータイムで再送信すると、tcp_synack_retries が 2 であるため、再送信の最大回数に達しているため、それでも失敗する場合は、しばらく待ちます (時間は前回のタイムアウトの 2 倍の時間です)。 receive クライアントの 3 回目のハンドシェイク (ACK メッセージ) の後、サーバーは切断されます。
3 回目の握手が失われました。
クライアントはサーバーから SYN-ACK メッセージを受信した後、サーバーに ACK メッセージを返します。これが 3 回目のハンドシェイクであり、クライアントの状態はこの時点でESTABLISH
状態に
3 回目のハンドシェイクの ACK は 2 回目のハンドシェイクの SYN の確認メッセージであるため、3 回目のハンドシェイクが失われた場合、サーバー側が確認メッセージの受信に失敗すると、タイムアウトの再起動がトリガーされます。 3 回目のハンドシェイクが受信されるまで、または再送信の最大数に達するまで、SYN-ACK メッセージ。
なお、ACK メッセージは再送されず、ACK が失われた場合は、対応するメッセージが相手から再送されます。
たとえば、tcp_synack_retries のパラメータ値が 2 であると仮定すると、3 回目のハンドシェイクが失われたときに発生するプロセスは次のようになります。
特定のプロセス:
- サーバーが SYN-ACK メッセージを 2 回オーバータイムで再送信すると、tcp_synack_retries が 2 であるため、再送信の最大回数に達しているため、それでも失敗する場合は、しばらく待ちます (時間は前回のタイムアウトの 2 倍の時間です)。 receive クライアントの 3 回目のハンドシェイク (ACK メッセージ) の後、サーバーは切断されます。
TCP 4 ウェーブ パケット ロスの状況
最初の波は失われましたが、どうなりますか?
クライアント (アクティブにパーティを閉じる) が close 関数を呼び出すと、クライアントはサーバーに FIN メッセージを送信し、サーバーから切断しようとします。クライアントの接続はこの時点でFIN_WAIT_1
状態
通常、サーバー(パッシブクロージングパーティ)からの ACK が間に合うように受信できれば、すぐにFIN_WAIT2
状態。
If the first wave is lost, and the client fails to receive ACK from the passive party, it will trigger the timeout retransmission mechanism and retransmit the FIN message. 再送信の回数は、tcp_orphan_retries
パラメーター
クライアントが FIN メッセージを再送信する回数がtcp_orphan_retries
を超える、クライアントは FIN メッセージを送信しなくなり、一定時間待機します (時間は前回のタイムアウト時間の 2 倍です)。第二波、それからclose
州。
たとえば、tcp_orphan_retries のパラメーター値が 3 であるとすると、最初のウェーブが常に失われる場合、発生するプロセスは次のようになります。
特定のプロセス:
- タイムアウト後にクライアントが FIN メッセージを 3 回再送信すると、tcp_orphan_retries が 3 であるため、再送信の最大回数に達しているため、サーバーがまだ失敗する場合は、しばらく待ちます (時間は前回のタイムアウト時間の 2 倍です)。 2 番目の波 (ACK メッセージ) を受信すると、クライアントは切断されます。
第二波は失われましたが、どうなりますか?
サーバーがクライアントからの最初の手を振ると、最初に ACK 確認メッセージを返し、サーバーの接続はこの時点のCLOSE_WAIT
状態に。
ACK メッセージは再送信されないことも前述したので、サーバーの 2 番目のウェーブが失われた場合、クライアントはタイムアウト再送信メカニズムをトリガーし、サーバーの最初のウェーブを受信するまで FIN メッセージを再送信します。再送回数。
たとえば、tcp_orphan_retries のパラメーター値が 2 であるとすると、2 番目のウェーブが常に失われる場合、発生するプロセスは次のようになります。
特定のプロセス:
- tcp_orphan_retries が 2 であるため、クライアントが FIN メッセージを 2 回再送信すると、再送信の最大回数に達したため、サーバーがまだ失敗する場合は、一定時間待機します (時間は前回のタイムアウト時間の 2 倍です)。 2 番目の波 (ACK メッセージ) を受信すると、クライアントは切断されます。
ここで、クライアントが 2 番目の wave を受信したとき、つまり、サーバーから送信された ACK メッセージを受信した後、クライアントはFIN_WAIT2
の状態 、つまり、 FIN メッセージのサービス終了です。
close 関数によって閉じられた接続の場合、データを送受信できなくなるため、FIN_WAIT2
状態が長く続くことはなく、この状態での接続の継続時間tcp_fin_timeout
を制御します。デフォルト値は 60 秒です。
これは、次の図に示すように、close の呼び出しによって閉じられた接続の場合、FIN メッセージが 60 秒後に受信されない場合、クライアント (アクティブなクローズ パーティ) の接続が直接閉じられることを意味します。
ただし、アクティブなクロージング パーティがシャットダウン関数を使用して接続を閉じる場合、送信方向のみがクローズされ、受信方向はクローズされないことを指定した場合、アクティブなクロージング パーティは引き続きデータを受信できることを意味します。
このとき、アクティブな閉鎖側が第 3 波を受信していない場合、アクティブな閉鎖側の接続は常にFIN_WAIT2
状態(tcp_fin_timeout
シャットダウンによって切断された接続は制御できません)。以下に示すように:
第三波は失われましたが、どうなりますか?
サーバー(パッシブ クロージング パーティ)がクライアント(アクティブ クロージング パーティ)から FIN メッセージを受信すると、カーネルは自動的に ACK を返し、接続はCLOSE_WAIT
の状態に
現時点では、カーネルにはプロセスを置き換えて接続を閉じる権利がなく、プロセスはクローズ関数をアクティブに呼び出して、サーバーが FIN メッセージを送信するようにトリガーする必要があります。
サーバーが CLOSE_WAIT 状態にあり、close 関数が呼び出されると、カーネルは FIN メッセージを送信し、同時に接続は LAST_ACK 状態に入り、クライアントが ACK を返して接続が閉じていることを確認するのを待ちます。
ACK が長期間受信されない場合、サーバーは FIN メッセージを再送信しますが、再送信されるtcp_orphan_retrie
FIN メッセージの再送信回数の制御方法と同じである s パラメータによって再送信回数が制御されます。クライアントによって。
たとえば、tcp_orphan_retrie
s = 3 と仮定すると、第 3 波が常に失われる場合、発生するプロセスは次のようになります。
特定のプロセス:
- サーバーが3回目のwavingメッセージを再送する回数が3回に達すると、tcp_orphan_retriesが3なので最大再送回数に到達するので、しばらく待ちます(時間は前回のタイムアウト時間の2倍です)。クライアントからの第 4 波 (ACK メッセージ) が受信されない場合、サーバーは切断されます。
- クライアントは close 関数でコネクションを切断するため、FIN_WAIT_2 状態には時間制限があり、サーバーからの第 3 ウェーブ (FIN メッセージ) が tcp_fin_timeout 時間内に受信されない場合、クライアントは切断されます。
第 4 波が失われましたが、どうなりますか?
クライアントがサーバーから 3 番目の手の波の FIN メッセージを受信すると、ACK メッセージ、つまり 4 番目の手の波を返し、クライアント接続はこの時点のTIME_WAIT
状態
Linux システムでは、クローズ状態に入る前に TIME_WAIT 状態が 2MSL 続きます。
次に、サーバー (パッシブ クロージング パーティ) が ACK メッセージを受信しない前は、まだ LAST_ACK 状態にあります。
4 番目の手の波の ACK メッセージがサーバーに届かない場合、サーバーは FIN メッセージを再送信しますが、再送信の回数は上記で紹介したtcp_orphan_retries
パラメーター
たとえば、tcp_orphan_retries が 2 であると仮定すると、4 回目の手振りが常に失われる場合、発生するプロセスは次のようになります。
特定のプロセス:
- サーバーが 3 回目の wave メッセージを再送信して 2 に達した時点で、tcp_orphan_retries が 2 であるため、再送信の最大回数に達しているため、まだ失敗する場合は、しばらく待ちます (時間は前回のタイムアウトの 2 倍の時間です)。クライアントの第 4 波 (ACK メッセージ) を受信すると、サーバーは切断されます。
- 3 番目のウェーブを受信した後、クライアントは TIME_WAIT 状態に入り、2MSL の期間でタイマーを開始します. 途中でクライアントが 3 番目のウェーブ (FIN メッセージ) を再度受信すると、タイマーをリセットします. 待機時 2MSL 期間の後、クライアントは切断されます。
以上!
どうですか、もうクリアですか?
その他のウェブ記事
ウェブサイト: xiaolincoding.com
-
ネットワークの基本
-
HTTP 記事
-
TCP
- TCP 3 ウェイ ハンドシェイクおよび 4 ウェイ Wave インタビューの質問
- TCP 再送信、スライディング ウィンドウ、フロー制御、輻輳制御
- TCP実戦パケットキャプチャ解析
- TCP セミコネクション キューとフルコネクション キュー
- TCP を最適化する方法は?
- TCP がバイト ストリーム プロトコル向けであることを理解するにはどうすればよいですか?
- TCP が接続を確立するたびに初期化シーケンス番号が異なるのはなぜですか?
- SYN パケットはいつ破棄されますか?
- 4 つのウェーブで受信された順不同の FIN パケットを処理する方法は?
- TIME_WAIT 状態の TCP 接続の場合、SYN を受信した後はどうなりますか?
- TCP 接続、一方の端での停電、およびプロセスのクラッシュの違いは何ですか?
- ネットワーク ケーブルを抜いた後、元の TCP 接続はまだ存在しますか?
- tcp_tw_reuse がデフォルトで無効になっているのはなぜですか?
- HTTPS で TLS と TCP のハンドシェイクを同時に行うことはできますか?
- TCP キープアライブと HTTP キープアライブは同じものですか?
- TCPの何が問題になっていますか?
- UDP プロトコルに基づいて信頼性の高い伝送を実現するにはどうすればよいですか?
- TCP と UDP は同じポートを使用できますか?
- サーバーがリッスンせず、クライアントが接続の確立を開始するとどうなりますか?
- accpetなしでTCP接続を確立できますか?
- TCP プロトコルでは、データが失われませんか?
-
知財記事
-
学習経験