コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

3-way ハンドシェイク

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

3-way ハンドシェイク とは

TCP コネクションを確立する SYN/SYN-ACK/ACK の流れを学びます。本レッスンでは、3-way ハンドシェイク の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

このレッスンで学ぶこと

TCP コネクションを確立する 3-way ハンドシェイクの流れを、SYN / SYN-ACK / ACK というフラグの意味を踏まえて理解します。

ハンドシェイクの目的

TCP は信頼性を保証するプロトコルなので、通信前に「お互いに連絡を取り合える状態か」を確認する必要があります。これがハンドシェイクです。

具体的には次の 2 つを確立します。

  1. 双方向の通信が可能であること
  2. 開始シーケンス番号 (ISN) の同期

シーケンス番号は、後で再送やパケット並び替えに使うので、最初に同期しておく必要があります。

3-way ハンドシェイクの流れ

クライアント C がサーバー S に接続するとき、3 つのパケットがやりとりされます。

  1. C → S — SYN, seq=x
  2. S → C — SYN, ACK, seq=y, ack=x+1
  3. C → S — ACK, seq=x+1, ack=y+1

それぞれの意味は次のとおりです。

  • SYN (Synchronize) — 「接続したい」「自分の初期シーケンス番号は x」
  • SYN, ACK — 「接続を受け入れる」「自分の初期シーケンス番号は y」「あなたの x+1 まで受け取ったよ」
  • ACK — 「了解」「あなたの y+1 まで受け取ったよ」

この 3 ステップで両方向の状態を整え、データのやりとりを始めます。

この章のポイント

なぜ 2 回ではダメか

クライアントが SYN を送る → サーバーが ACK を返す、の 2 ステップでは、サーバーから見ると「自分の応答パケットが本当にクライアントに届いたか」が分かりません。3 ステップ目のクライアントからの ACK で、両方向の到達性が確定します。

SYN パケットの中身

実際の TCP セグメントのヘッダーには、フラグビットがいくつもあります。

  • SYN — 同期 (接続開始)
  • ACK — 確認応答
  • FIN — 切断要求
  • RST — 強制リセット
  • PSH — バッファリングせず即時送信
  • URG — 緊急データ

3-way ハンドシェイクで使うのは SYN と ACK の組み合わせだけです。

4-way クローズ

接続を閉じるときは 4-way クローズという手順を踏みます。

  1. C → S — FIN
  2. S → C — ACK
  3. S → C — FIN
  4. C → S — ACK

FIN を送る側は「もうデータを送らない」と宣言します。ただし、受信側がまだ送りたいデータを持っているかもしれないので、双方向別々にクローズします。

開始は 3 回、終了は 4 回、と覚えておきましょう。

SYN フラッド攻撃

3-way ハンドシェイクの仕組みを悪用した攻撃に SYN フラッドがあります。

攻撃者は大量の SYN パケットだけを送りつけ、ACK を返しません。サーバーは「半開きのコネクション」を保持し続け、リソースを使い切ってしまいます。

対策として、SYN Cookie (サーバー側で状態を保持せずに SYN-ACK を返す技術) や、ファイアウォールでのレート制限が使われます。

この章のポイント

コネクション確立はコストがかかる

3-way ハンドシェイクは 1 往復半のラウンドトリップを必要とします。光ファイバーでも RTT は数ミリ秒~数十ミリ秒。何度も接続を開閉するアプリは、この往復回数だけでも体感が遅くなります。HTTP/2 の多重化や、TLS 1.3 の 0-RTT、QUIC の素早い接続確立は、この往復回数を減らす工夫です。

ハンドシェイクをパケットで観察する

実際に tcpdump や Wireshark で見ると、3 行が並んで見えます。

プレーンテキスト

10:00:00.001 IP client.54321 > server.443: Flags [S], seq 1000 10:00:00.011 IP server.443 > client.54321: Flags [S.], seq 2000, ack 1001 10:00:00.012 IP client.54321 > server.443: Flags [.], ack 2001

S が SYN、S. が SYN+ACK (. は ACK の意味)、. だけが純粋な ACK です。

まとめ

TCP は通信前に SYN / SYN-ACK / ACK の 3-way ハンドシェイクで双方向の到達性とシーケンス番号を確認します。終了時は 4-way クローズ。1 接続あたり 1 往復半のラウンドトリップが必要なので、Web の高速化では「接続を使い回す」「往復回数を減らす」が大事なテーマになります。次のレッスンでは、混雑時に流量を調整する輻輳制御を学びます。

よくある質問

Q. このトピックは実務でどう役立ちますか?

A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。

Q. SYN フラッドはどう防ぐのですか?

A. 代表的な対策が SYN Cookie です。サーバーは半開きのコネクションを保持する代わりに、SYN-ACK に暗号学的なシーケンス番号を埋め込み、最後の ACK が届いたときだけ状態を作ります。これにより攻撃者がメモリを枯渇させることを防げます。ファイアウォールやロードバランサーでの SYN レート制限も併用されます。

Q. なぜ接続クローズは 4-way で、確立は 3-way なのですか?

A. 確立時はサーバーが SYN と ACK を 1 パケットにまとめられるため 3 回で済みます。クローズ時はサーバーがまだ送り終えていないデータを持っている場合があるので、FIN と ACK を別タイミングで送る必要があり 4 回になります。ただし送りかけのデータがなければサーバー側の ACK と FIN を 1 パケットにまとめて 3 パケットで終わることもあります。

Q. TIME_WAIT とは何ですか?

A. アクティブクローズ側(最後の ACK を送った側)が、一定時間(通常 2 MSL=最大 2 分程度)コネクション情報を保持する状態です。遅延パケットが後から届いても新しいコネクションと混同しないようにするための安全マージンです。短命な接続を大量に張るサーバーでは TIME_WAIT が多数残るため、SO_REUSEADDR などで緩和することがあります。

次のレッスン

次は 輻輳制御と再送 で、ネットワークが混雑したときに送信レートを自動調整する仕組みを学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 3-way ハンドシェイク の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 3-way ハンドシェイク とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

復習ミニクイズ

TCP の 3-way ハンドシェイクで送信されるフラグの順序として正しいものはどれですか