TCPハンドシェイクの仕組み — 3回のあいさつで何を確かめる?
「始めるよ」「こちらも」「確認したよ」
まずは、3つのメッセージを読む
電話で話し始める前のあいさつのように、TCPでは接続開始時に双方の情報を合わせます。基本的な3ウェイハンドシェイクの例を、クライアントとサーバーの間で読んでみましょう。
| 順番 | 方向 | フラグ | SEQ | ACK番号 |
|---|---|---|---|---|
| ① | クライアント → サーバー | SYN | 1000 | この例では使わない |
| ② | サーバー → クライアント | SYN, ACK | 5000 | 1001 |
| ③ | クライアント → サーバー | ACK | 1001 | 5001 |
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