ネットワークの教科書NETWORK

第4章 通信の制御4-2コース全体 19回中14本目

入門読了 約8分

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回のやりとりで接続を確立します。 このとき同時に、お互いが「どの番号からデータを数え始めるか」(開始番号)を伝え合います。

クライアントサーバ① SYN送信seq=1000② SYN+ACKで応答seq=4000 ack=1001③ ACKで確認ack=4001
クライアントは自分の開始番号(seq=1000)を伝えるSYNを送る。サーバはその受信を確認しつつ(ack=1001)、自分の開始番号(seq=4000)を伝えるSYN+ACKを返す。クライアントはサーバの開始番号の受信を確認するACK(ack=4001)を返し、双方の開始番号が確認し合えたところで接続が確立する。

開始番号は本来ランダムな32ビットの値ですが、ここでは説明のためにクライアント側を1000、サーバ側を4000とします。

やりとり向きseqack
① SYNクライアント → サーバ1000
② SYN+ACKサーバ → クライアント40001001
③ ACKクライアント → サーバ10014001

①でクライアントは自分の開始番号(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が返らなければ、そのデータをロスト(失われた)とみなして同じデータを再送します。

クライアントサーバ① データ送信seq=1001(200バイト)消失② タイムアウトACK待ち・応答なし③ 再送seq=1001(同じデータ)④ ACKで確認ack=1201
クライアントが送ったデータ(seq=1001、200バイト)が途中で失われ、サーバに届かなかった。一定時間(タイムアウト)が経ってもACKが返らないため、クライアントは同じデータをもう一度送り、今度はサーバに届いてack=1201が返ってきた。

再送してもACKが返らなければ、さらに時間をおいて再送を繰り返します。この待ち時間(タイムアウト)は 通信の状況に応じて調整され、途中でデータが失われても、最終的には確実に届くしくみになっています。

しくみ

ウィンドウサイズ ― 1つずつ待たないしくみ

ここまでの説明どおり1つ送ってACKを待ち、また1つ送ってACKを待つ、を繰り返すと、 往復にかかる時間の分だけ通信全体が遅くなってしまいます。そこでTCPはACKを待たずに、まとめて送ってよいデータ量(ウィンドウサイズ)を決めておき、 その範囲内なら次々とデータを送り出せるようにしています。

ウィンドウサイズは受信側の処理能力や回線の混み具合に応じて動的に変わり、調整の詳しいアルゴリズム (スロースタートなど)はここでは扱いません。「1つずつ待つと遅いから、まとめて送れる量を決めている」 という理由だけ押さえておけば十分です。

補足

接続の終了はFINで行う

接続を終えるときは、SYNの代わりにFINという制御フラグを使います。FINもSYNと同じく シーケンス番号を1つ消費するため、相手からのACKで確認されます。データは双方向に流れているので、 それぞれの方向で「もう送るデータはない」という意思表示(FIN)と確認(ACK)が必要になり、 合計4回のやりとりで接続を閉じます。

練習

練習問題(全5問)

選んでから「採点する」を押すと、解説つきで答え合わせができます。

Q1クライアントがseq=2000のSYNを送ったとき、サーバが返すSYN+ACKのack番号は?
Q2なぜSYN→ACKの2回のやりとりだけでは接続を確立できないのか?
Q3送信したデータのACKが一定時間内に返ってこなかった場合、送信側はどうする?
Q4ウィンドウサイズの役割として正しいものは?
Q5TCP接続を終了するときに使われる、SYNとは別の制御フラグは?
次の回

コースを読み進める