第4章 通信の制御|4-2|コース全体 19本中14本目
TCPの3ウェイハンドシェイクと再送制御
TCPは、
前の記事 ・4-1 TCPとUDPの違い ― どっちを使うべきか
TCPは「確認しながら送り、届かなければ送り直す」ことで、届いたか分かるようにしている
TCPは、受信確認(ACK)で到達を確かめ、届かなければ再送します。この仕組みがあるので、Webページやメールは途中が欠けずに届きます。UDPには、この仕組みがありません。
TCPは通信を始める前に、3回のやりとりでお互いの準備を確認します。これを3ウェイハンドシェイクと呼びます。データを送るときは、どこまで送ったかをシーケンス番号で管理します。
相手からのACKが一定時間内に返らなければ、TCPは同じデータを再送します。ハンドシェイク・シーケンス番号・再送の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で確認します。これで双方が相手の開始番号を確認できたので、データの送信を始められます。
①と②では、1つのセグメント(TCPの送信単位)に載せられるデータの上限も相手に知らせます。この上限の値は、MTUとMSSの記事で説明しています。
なぜSYN→ACKの2回のやりとりでは足りないのか
TCPの通信では、クライアントからサーバへも、サーバからクライアントへもデータが流れます。そのため、クライアントとサーバがそれぞれ自分の開始番号を持ち、どちらの開始番号も相手に確認してもらう必要があります。
もし①SYN、②ACKの2回だけで終わらせると、①で伝えたクライアントの開始番号は確認できます。サーバも、②のACKで自分の開始番号を伝えることはできます。しかし、クライアントがそれを受け取ったことを、サーバは確認できません。
この最後の確認を行うのが、③のACKです。だから、2回ではなく3回のやりとりが必要になります。時間にすると、SYNとSYN+ACKで1往復、ACKでさらに片道分の、1往復半かかります。
ただし、③のACKにはデータを一緒に載せられるので、データを送り始められるのは1往復後からです。
HTTP/3が使うQUICはTCPを使わず、接続の準備と暗号の準備を1往復にまとめます。TCPとの往復の差は、HTTP/3とQUICの記事の図で比べられます。
サーバは、①を受けると、③が届くまで接続の情報を保持します。この性質を悪用し、③を返さないSYNを大量に送って受付の枠を使い切らせる攻撃が、SYNフラッドです。
シーケンス番号とACK番号が数えているもの
シーケンス番号とACK番号は、パケットの個数ではなくバイト数を数えています。表では、シーケンス番号をseq、ACK番号をackと書いています。
SYNとFINは中身のデータを持ちませんが、それぞれ1バイト分の番号を消費する決まりです。ハンドシェイクのack番号が「相手のseq + 1」になっているのは、このためです。
データを送るときも同じです。たとえばハンドシェイクの後、クライアントが200バイトのデータをseq=1001から送ると、サーバはack=1201を返します。これは「1001番目から1200番目までの200バイトを受け取った。次は1201番目を待っている」という意味です。
このようにACK番号は、次に受け取りたいバイトの番号であり、それより前のバイトがすべて届いたことも表します。この確認のしかたを累積の確認応答と呼びます。
再送制御:ACKが返らないとどうなるか
TCPの再送は、書留郵便の受領印に近い考え方です。送った側は、受領印が返ってくるまで、本当に届いたかどうかを確認できません。TCPでは、ACKがこの受領印にあたります。
そこでTCPは、データを送るたびにタイマーを開始します。一定時間内にACKが返らなければ、そのデータは失われたとみなし、同じデータを再送します。データが途中で失われることをロストと呼びます。
再送してもACKが返らなければ、さらに時間をおいて再送を繰り返します。ただし、再送の回数には上限があり、それでも届かなければ接続を失敗とします。
つまりTCPは、データが届くか、届かなかったことを送信側が把握できる仕組みで、必ず届くわけではありません。
ウィンドウサイズ:1つずつ待たないしくみ
ここまでの説明では、1つ送るたびにACKを待っていました。しかし、これでは往復にかかる時間の分だけ、通信全体が遅くなってしまいます。
そこでTCPは、ACKを待たずに、まとめて送ってよいデータ量を決めておきます。その範囲内なら、次々とデータを送り出せます。
まとめて送れる量を決める仕組みは2つあります。1つは、受信側が、自分が処理できる量をTCPヘッダのウィンドウサイズ欄で伝える仕組みで、フロー制御と呼びます。フロー制御という考え方自体は、データリンク層の通信手順にもあります。その手順は、伝送制御の記事で説明しています。
もう1つは、送信側が回線の混み具合を見て、送る量を調整する仕組みで、輻輳(ふくそう)制御と呼びます。輻輳制御では、少ない量から始めて、ACKが返るたびに送信量を増やしていきます。
実際に送ってよい量は、この2つのうち小さい方に制限されます。
接続の終了はFINで行う
接続を終えるときは、SYNの代わりにFINという制御フラグを使います。FINもSYNと同じくシーケンス番号を1つ消費するので、相手からのACKで確認されます。
データは双方向に流れているので、それぞれの方向で終わりを伝える必要があります。「もう送るデータはない」という意思表示がFINで、それに対する確認がACKです。両方向でFINとACKを交わすので、合計4回のやりとりで接続を閉じます。この閉じ方を4ウェイクローズと呼びます。
TCPヘッダには、どのアプリ宛てかを示す番号も入っています。それがポート番号です。
3回のやりとりが実際にどう見えるかは、Wiresharkの記事の疑似パケット一覧で確認できます。
練習問題(全5問)
正解:2001
SYNは
正解:サーバが
接続は
正解:同じ
TCPは、
正解:ACKを
1つ
正解:FIN
接続を
選んでから「採点する」を押すと、解説つきで答え合わせができます。
おすすめの本 PR
この記事の内容を扱っている本です。
![『[改訂新版]3分間ネットワーク基礎講座』の表紙](https://m.media-amazon.com/images/P/4774143731.09.MZZZZZZZ.jpg)