最終更新:

TCPハンドシェイクの仕組み — 3回のあいさつで何を確かめる?


「始めるよ」「こちらも」「確認したよ」

クライアントサーバー① SYN:SEQ 1000② SYN, ACKSEQ 5000 / ACK 1001③ ACK:ACK 50013つのメッセージで、開始を合わせる
矢印は送信方向、縦は順番です。番号は説明用で、実際の固定設定ではありません。接続の開始と、HTTPで目的の処理が成功することは別です。
ひよこ ひよこ
Webページを開く前に、3回あいさつするって本当?
ペンギン先生 ペンギン先生
TCPで接続を始める基本例では、SYN、SYNとACK、ACKの3つのメッセージを交換するよ。片道のやり取りを3回という意味で、3往復ではないんだ。HTTP/3などTCPを使わない通信は別の仕組みだよ。
ひよこ ひよこ
ただ「聞こえる?」と確かめているの?
ペンギン先生 ペンギン先生
それに加えて、双方が送り始めるシーケンス番号を知らせ、相手の開始を確認するよ。古い接続の情報との混同を防ぐことにも関わる。接続後にずっと通信できるという保証まではしないんだ。
ひよこ ひよこ
SYNって何の合図?
ペンギン先生 ペンギン先生
開始番号を同期するためのフラグだよ。ここではクライアントが例の番号1000を知らせる。その番号は説明用で、実際に1000へ固定して設定するものではないんだ。
ひよこ ひよこ
サーバーがSYNとACKを一緒に返すのは?
ペンギン先生 ペンギン先生
相手の開始を確認するACKと、自分の開始番号を知らせるSYNをまとめるためだよ。例では自分が5000から始め、相手には次の1001を待っていると知らせる。
ひよこ ひよこ
1000を確認したのに、ACKは1001になるの?
ペンギン先生 ペンギン先生
ACK番号は、次に受け取りたい番号を示すからだよ。SYNも番号を1つ使う。データを送るときはバイト数で番号が進み、メッセージの個数を数える番号とは違うんだ。
ひよこ ひよこ
最後のACKが届けば、ページも表示できた?
ペンギン先生 ペンギン先生
TCPの接続成立とWebの成功は別だよ。その後にTLSやHTTPのやり取りが必要な場合がある。TCPでつながっても、認証エラーやサーバーのHTTPエラーは起こり得るんだ。
ひよこ ひよこ
終わるときは、必ず4回のあいさつ?
ペンギン先生 ペンギン先生
基本的なFINとACKの例は4つで説明できるけれど、ACKとFINをまとめたり、両方が同時に閉じたり、RSTで中断したりする。TIME_WAITは前の接続の情報を扱うための待ちで、単なる失敗の印ではないよ。
ひよこ ひよこ
接続が遅いなら、待ち時間を消せばいい?
ペンギン先生 ペンギン先生
設定をむやみに変える前に、DNS、接続、TLS、HTTP応答のどこで待っているかを分けよう。接続の再利用も候補だけど、経路やサービスの条件による。まずは下の番号のやり取りを読めれば十分だよ。

まずは、3つのメッセージを読む

電話で話し始める前のあいさつのように、TCPでは接続開始時に双方の情報を合わせます。基本的な3ウェイハンドシェイクの例を、クライアントとサーバーの間で読んでみましょう。

順番方向フラグSEQACK番号
①クライアント → サーバーSYN1000この例では使わない
②サーバー → クライアントSYN, ACK50001001
③クライアント → サーバーACK10015001

3回は3往復ではなく、3つのメッセージです。番号は理解用の例であり、設定値ではありません。図の矢印はその送信方向を示します。

ACKは「次に欲しい番号」

サーバーはクライアントのSYNを受け取り、ACKに1001を入れます。SYNが1000を1つ使ったので、次を1001として待つためです。同様にクライアントはサーバーの5000を受け、5001を返します。

TCPの番号はバイト列の位置を扱います。データが100バイトならその分だけ進みます。データもSYNもFINもないACKだけでは、番号を1つ消費するわけではありません。

接続成立と、ページ表示の成功は別

TCPは順序や再送などでバイト列の転送を扱いますが、途中でネットワークが切れることもあります。ACKはアプリが注文処理やDB保存を完了したという意味ではありません。

HTTPSをTCP上で使う場合はTLSのやり取りもあり、その上でHTTPの要求と応答を行います。一方、HTTP/3はQUICを使うため、このTCPの図をそのまま当てはめません。

もう少し詳しく:接続を閉じるとき

FINは「こちらから送るデータは終わった」という合図です。一方が送信を終えても、反対方向のデータを受け取る半閉じの状態があります。正常な終了をFINとACKの4つで示す図は基本例で、実際には組み合わせや同時終了、RSTによる中断もあります。

能動的に閉じる側のTIME_WAITは、遅れて来る古い情報や最後の確認等を扱うための状態です。RFCは2×MSLの待ちを規定していますが、MSLや実装の挙動を確かめず「どのOSでも60秒」とは言えません。数が多いときも、直ちに不要な状態として削除する判断はしません。

通常の接続同期でもデータを含む場合はあります。TCP Fast Open等の最適化はさらに別の条件を持つので、「SYNにデータは絶対入らない」「いつでも待ちが半分になる」とも説明しません。

🐧 ペンギン先生のまとめ:「TCPハンドシェイク」って出てきたら「話し始める前に、双方の開始番号を合わせるあいさつ」と思えばだいたいOK!

次は、通信の保護をHTTPとHTTPSの違い、接続先の名前を調べる流れをDNSの仕組みで見てみましょう。

参考資料

  • RFC 9293:TCP — 基本の3メッセージ・番号・接続同期と終了・TIME_WAIT