はじめに
TCPは、HTTP/1.1やHTTP/2によるWebサイトの閲覧、メール、ファイル転送など、データの欠損や順序の入れ替わりを避けたい通信で利用されます。しかし、IPネットワークでは、送ったデータが途中で失われたり、到着順が入れ替わったりすることがあります。また、受信側の処理能力やネットワークの混雑状況も一定ではありません。
TCPは、通信状態を管理しながら、シーケンス番号と確認応答、再送、フロー制御、輻輳制御を組み合わせ、アプリケーションへ信頼性のある順序どおりのバイトストリームを提供します。この記事では、TCPがデータを確実に届け、状況に応じて送信量を調整する仕組みを解説します。
この記事で分かること
- TCPが提供する信頼性の意味
- シーケンス番号と確認応答の役割
- データ損失を検出して再送する仕組み
- フロー制御と輻輳制御の違い
- 受信ウインドウと輻輳ウインドウの関係
TCPの機能とは
TCP(Transmission Control Protocol)は、通信する端点間で接続状態を管理するコネクション型のトランスポートプロトコルです。アプリケーションが渡したデータをバイトの連続として扱い、受信側へ同じ順序で渡します。
TCPの主な制御は、次の3つに整理できます。
| 機能 | 解決する問題 | 主な仕組み |
|---|---|---|
| 信頼性と順序制御 | データの損失、重複、順序の入れ替わり | シーケンス番号、確認応答、再送 |
| フロー制御 | 受信側が処理できる量を超えて送ること | 受信ウインドウ |
| 輻輳制御 | ネットワークへ過剰なデータを送り、混雑を悪化させること | 輻輳ウインドウ、送信量の増減 |
シーケンス番号、確認応答番号、ウインドウ、制御フラグなどをTCPヘッダー内でどのように配置するかは、TCPヘッダーとは?各フィールドと制御フラグの役割を解説で解説しています。
TCPとUDPを含むトランスポート層全体の役割は、トランスポート層とは?役割とTCP・UDPの違いを分かりやすく解説で解説しています。
TCPは接続状態を管理する
TCPはデータを送る前に、3ウェイハンドシェイクで接続を確立します。両端が初期シーケンス番号を交換して確認することで、これから送受信するデータの位置を管理できる状態にします。
通信を終了するときは、FINとACKを使って、それぞれの送信方向を閉じます。ただし、FINとACKを別々のセグメントで送る場合も、同じセグメントにまとめる場合もあるため、接続から切断までの通信回数は常に同じではありません。
コネクションが表す論理的な通信状態と、再送や順序制御との違いは、コネクション型とコネクションレス型の違い|TCP・UDPの具体例で解説を参照してください。
TCPが信頼性と順序を実現する仕組み
シーケンス番号でデータの位置を管理する
TCPは、送信するバイトごとにシーケンス番号を割り当てます。TCPセグメントのシーケンス番号は、そのセグメントに含まれる先頭データのバイト位置を表します。
受信側はシーケンス番号を確認することで、次に必要なデータ、重複して届いたデータ、順序が入れ替わったデータを判別できます。順序が入れ替わって届いた場合も、必要なデータがそろえば、アプリケーションへは正しい順序で渡します。
確認応答で次に必要なデータを伝える
受信側はACK(確認応答)を返し、次に受信したいシーケンス番号を送信側へ伝えます。例えばACK番号が5000なら、4999までのデータを連続して受信し、次は5000から必要であることを表します。
TCPは、破損したデータにNACKを返す方式を基本にはしていません。送信側は、ACK番号が進まないことや再送タイマーの満了などから、データが失われた可能性を判断します。
損失を検出したデータを再送する
送信側は、確認応答されていないデータを保持し、損失を検出すると再送します。再送の主な契機は、再送タイムアウトと重複ACKです。
再送タイムアウトは、計測したRTT(往復時間)の平均だけでなく、遅延の変動も考慮して調整されます。タイムアウトが繰り返される場合は、再送タイムアウトを指数的に長くし、混雑している可能性があるネットワークへ短い間隔で再送を繰り返さないようにします。
一方、同じACK番号を持つ重複ACKが繰り返し返ると、後続データは届いているものの、その手前のデータが欠けていると推測できます。典型的なTCPでは、3つの重複ACKを受信すると、タイムアウトを待たずに欠けたデータを再送する高速再送を行います。
フロー制御は受信側の処理能力に合わせる
フロー制御は、受信側が保持できるデータ量に合わせて、送信側の送信量を制限する仕組みです。受信側はTCPヘッダーのウインドウフィールドを使い、現在受け入れられるデータ量を受信ウインドウとして通知します。
アプリケーションの処理が追いつかず受信バッファの空きが少なくなると、受信側は小さいウインドウを通知します。空きがなくなった場合はウインドウを0にでき、送信側は新しいデータの通常送信を止めます。その後はゼロウインドウプローブを送り、受信側が再び受け入れられる状態になったかを確認します。
フロー制御が守る対象は、ネットワーク全体ではなく受信側の端末です。
輻輳制御はネットワークの混雑を抑える
輻輳制御は、通信経路の処理能力を超える量のデータを送り、ネットワークの混雑を悪化させないための仕組みです。送信側は輻輳ウインドウを管理し、確認応答が順調に返る間は送信可能量を増やし、損失などから混雑を検出した場合は送信可能量を減らします。
通信開始時など、経路で利用できる容量が分からない段階では、スロースタートによって小さな送信量から始めます。その後は増加を緩やかにする輻輳回避へ移ります。損失を検出した場合は、輻輳ウインドウを縮小し、同じ送信量を続けないようにします。
フロー制御と輻輳制御は目的が異なります。送信側が未確認のまま送信できるデータ量の上限は、受信側が通知する受信ウインドウと、ネットワーク状況から決める輻輳ウインドウの小さい方に制限されます。
まとめ
TCPは、接続状態を管理しながら、信頼性のある順序どおりのバイトストリームをアプリケーションへ提供します。
- シーケンス番号は、送信したデータの位置を管理する
- ACKは、受信側が次に必要とするシーケンス番号を伝える
- 損失は再送タイムアウトや重複ACKなどから検出し、必要なデータを再送する
- フロー制御は、受信側の処理能力に合わせて送信量を調整する
- 輻輳制御は、ネットワークの混雑状況に合わせて送信量を調整する
- 未確認のまま送信できる量は、受信ウインドウと輻輳ウインドウの小さい方で制限される
TCPの機能は、単に「届かなければ再送する」だけではありません。データの位置、受信側の空き容量、ネットワークの混雑という異なる状態を管理し、それぞれに応じて通信を制御することで信頼性を実現しています。


コメント