第4章 通信の制御|4-2|コース全体 19回中14本目
3ウェイハンドシェイクと再送制御 ― TCPが確実に届くしくみ
「TCP 3ウェイハンドシェイク 仕組み」で調べている人向け。SYN→SYN+ACK→ACKの意味、シーケンス番号とACK番号が何を数えているか、ACKが返らないときの再送のしくみを、具体的な数値と図で解説します。
TCPは「確認しながら送り、届かなければ送り直す」ことで確実さを実現している
前回「TCPとUDPの違い」で、TCPはACKで到達を確認し、届かなければ再送すると説明しました。 今回はその中身に踏み込みます。TCPは通信を始める前に3回のやりとり(3ウェイハンドシェイク)で お互いの準備を確認し、データを送るたびにシーケンス番号で「どこまで送ったか」を数え、 相手からのACKが一定時間内に返らなければ同じデータを再送します。この3つのしくみが、 「確実に届く」を実現している中身です。
3ウェイハンドシェイクの流れ
TCPはデータを送る前に、SYN・SYN+ACK・ACKの3回のやりとりで接続を確立します。 このとき同時に、お互いが「どの番号からデータを数え始めるか」(開始番号)を伝え合います。
開始番号は本来ランダムな32ビットの値ですが、ここでは説明のためにクライアント側を1000、サーバ側を4000とします。
| やりとり | 向き | seq | ack |
|---|---|---|---|
| ① SYN | クライアント → サーバ | 1000 | ― |
| ② SYN+ACK | サーバ → クライアント | 4000 | 1001 |
| ③ ACK | クライアント → サーバ | 1001 | 4001 |
①でクライアントは自分の開始番号(seq=1000)を伝えます。 ②でサーバは自分の開始番号(seq=4000)を伝えつつ、 クライアントの開始番号を受け取ったことをack=1001で確認します。 ③でクライアントは、サーバの開始番号を受け取ったことをack=4001で確認します。 ここまで終わると、双方が「相手の開始番号を確認できた」状態になり、データの送信を始められます。
なぜSYN→ACKの2回のやりとりでは足りないのか
TCPの通信はクライアントからサーバへも、サーバからクライアントへも、両方向にデータが流れます。 そのため開始番号も、クライアント側とサーバ側それぞれが自分のものを持ち、それぞれ相手に確認してもらう必要があります。
もし①SYN、②ACKの2回だけで終わらせると、①でクライアントの開始番号は確認できますが、 ②のACKでサーバが自分の開始番号を伝えたとしても、それをクライアントが受け取ったことをサーバ自身は確認できません。 この最後の確認を行うのが③のACKです。だから2回ではなく3回のやりとりが必要になり、 時間にすると1往復半(SYNとSYN+ACKで1往復、ACKでさらに片道分)かかります。
シーケンス番号とACK番号が数えているもの
シーケンス番号(seq)とACK番号(ack)は、パケットの個数ではなくバイト数を数えています。 SYNとFINは中身のデータを持ちませんが、それぞれ1バイト分の番号を消費するという決まりになっています。 ハンドシェイクのack番号が「相手のseq + 1」になっているのは、このためです。
データを送るときも同じ考え方です。たとえばハンドシェイクの後、クライアントが200バイトのデータをseq=1001から送ったとすると、サーバは「1001番目から1200番目までの200バイトを受け取った、 次は1201番目を待っている」という意味でack=1201を返します。 ACK番号は「次に受け取りたいバイトの番号」であり、これより前のバイトはすべて届いたことを表す累積の確認応答になっています。
再送制御 ― ACKが返らないとどうなるか
これは書留郵便の受領印に近い考え方です。送った側は「届きました」という受領印(ACK)が返ってくるまで、 本当に届いたかどうかを確認できません。だからTCPはデータを送るたびにタイマーを開始し、一定時間内にACKが返らなければ、そのデータをロスト(失われた)とみなして同じデータを再送します。
再送してもACKが返らなければ、さらに時間をおいて再送を繰り返します。この待ち時間(タイムアウト)は 通信の状況に応じて調整され、途中でデータが失われても、最終的には確実に届くしくみになっています。
ウィンドウサイズ ― 1つずつ待たないしくみ
ここまでの説明どおり1つ送ってACKを待ち、また1つ送ってACKを待つ、を繰り返すと、 往復にかかる時間の分だけ通信全体が遅くなってしまいます。そこでTCPはACKを待たずに、まとめて送ってよいデータ量(ウィンドウサイズ)を決めておき、 その範囲内なら次々とデータを送り出せるようにしています。
ウィンドウサイズは受信側の処理能力や回線の混み具合に応じて動的に変わり、調整の詳しいアルゴリズム (スロースタートなど)はここでは扱いません。「1つずつ待つと遅いから、まとめて送れる量を決めている」 という理由だけ押さえておけば十分です。
接続の終了はFINで行う
接続を終えるときは、SYNの代わりにFINという制御フラグを使います。FINもSYNと同じく シーケンス番号を1つ消費するため、相手からのACKで確認されます。データは双方向に流れているので、 それぞれの方向で「もう送るデータはない」という意思表示(FIN)と確認(ACK)が必要になり、 合計4回のやりとりで接続を閉じます。
練習問題(全5問)
選んでから「採点する」を押すと、解説つきで答え合わせができます。
正解:2001
SYNは1つのシーケンス番号を消費するため、相手が確認するack番号は「受け取ったseq + 1」になります。2000 + 1 = 2001です。
正解:サーバが自分の開始番号を伝え、それをクライアントが受け取ったことを確認する手順が抜けるから
接続は双方向です。クライアントの開始番号だけでなく、サーバの開始番号も相手に確認してもらう必要があります。SYN・SYN+ACKの2回では、サーバの開始番号が確認されたことをサーバ自身が知る手段がありません。3回目のACKが、その最後の確認にあたります。
正解:同じデータをもう一度送る(再送する)
TCPは届いた確認(ACK)が一定時間(タイムアウト)内に返らなければ、データが失われたとみなして同じデータを再送します。これを繰り返すことで、途中でデータが失われても最終的には確実に届けます。
正解:ACKを待たずにまとめて送れるデータ量を決め、通信を効率化する
1つ送るたびにACKを待っていると、往復にかかる時間の分だけ通信が遅くなります。ウィンドウサイズは「ACKを待たずにまとめて送ってよいデータ量」を決めるしくみで、これにより待ち時間を減らして効率よく送れます。
正解:FIN
接続を閉じる意思はFINフラグで伝えます。FINもSYNと同様にシーケンス番号を1つ消費するため、相手からのACKで確認されます。データは双方向で流れているため、両方向それぞれにFIN→ACKが必要になり、合計4回のやりとり(4ウェイクローズ)になります。