TCPとは?仕組み・ヘッダ・3ウェイハンドシェイクから輻輳制御・チューニングまで徹底解説

TCPとは何か — 概要

TCP(Transmission Control Protocol)は、インターネットにおけるコネクション型のトランスポート層プロトコルです。信頼性のあるデータ転送、順序制御、フロー制御、輻輳制御を提供し、アプリケーションはTCPを通じてストリームとしてデータをやり取りします。TCPはIPと組み合わせて動作し、一般に「TCP/IP」と総称されます。TCPの基礎仕様はRFC 793(1981年)で定義されています。

TCPの役割と特徴

  • 信頼性(Reliable delivery):データは欠落や重複がないように再送や確認応答(ACK)で保証されます。
  • 順序制御:受信側が送信順にデータを再構成します。パケットの順序が入れ替わってもアプリケーションには順序通りに渡されます。
  • フロー制御(Flow control):受信側の処理能力に合わせて送信レートを調整するためのウィンドウ制御を備えます。
  • 輻輳制御(Congestion control):ネットワーク混雑を検出して送信レートを抑制するアルゴリズム(スロースタート、輻輳回避、Fast Retransmit/Recovery など)を持ちます。
  • コネクション指向:通信を開始するために接続確立(3ウェイハンドシェイク)を行い、終了時には通常4ウェイで切断します。

TCPヘッダの主なフィールド

TCPヘッダは最小20バイトで、オプションを含め最大で拡張できます。主要なフィールドは次のとおりです:

  • 送信ポート/受信ポート(16bitずつ)
  • シーケンス番号(32bit)— バイトストリーム上の位置を示す
  • 確認応答番号(ACK、32bit)— 次に期待するシーケンス番号
  • データオフセット(ヘッダ長)、フラグ(URG, ACK, PSH, RST, SYN, FIN)
  • ウィンドウサイズ(16bit)— フロー制御用(拡張はウィンドウスケールオプション)
  • チェックサム(16bit)— ヘッダ+データの誤り検出
  • 緊急ポインタ(URG)およびオプション(MSS, Window Scale, Timestamps, SACK permitted など)

接続確立と切断

接続確立は「3ウェイハンドシェイク」で行われます:

  • クライアント → サーバ:SYN(ISN = x)
  • サーバ → クライアント:SYN+ACK(ISN = y、ACK = x+1)
  • クライアント → サーバ:ACK(ACK = y+1)

切断は通常4ウェイ(FIN/ACK の交換)で行われますが、同時終了やRST(即時終了)もあります。TIME-WAIT状態は遅延パケットや誤配信対応のために保持されます。

信頼性を支える仕組み

主要な技術要素:

  • シーケンス番号と確認応答(ACK)で受信確認を行う。ACKは累積確認が基本。
  • 再送:ACKが来ない場合やRTO(再送タイムアウト)に達した場合に再送。
  • SACK(Selective Acknowledgment):受信済みの範囲を明示でき、部分的な欠損回復に有効(RFC 2018)。
  • RTO計算:RTT推定と分散に基づくアルゴリズム(標準的な推奨はRFC 6298)。

フロー制御とウィンドウ

受信側はウィンドウサイズで自分が受け取れる未受領データ量を通知します。スライディングウィンドウ方式により、連続したバイト範囲の送信・確認が行われます。大きな帯域・遅延積(BDP:Bandwidth-Delay Product)環境では、Window Scaleオプション(RFC 1323/RFC 7323)を使って理論上1GB程度まで拡張できます。

輻輳制御(Congestion Control)

TCPの輻輳制御はネットワークを過負荷にしないための重要な機構です。代表的な手法:

  • スロースタート(Slow Start)— 送信ウィンドウを指数的に増加させる(初期は保守的)。
  • 輻輳回避(Congestion Avoidance)— 線形増加などで輻輳ウィンドウCWNDの増やし方を穏やかにする。
  • Fast Retransmit / Fast Recovery — 重複ACKを見て高速再送と一時的なCWND調整を行う(Reno/NewRenoなど)。
  • 近年のアルゴリズム:CUBIC(Linuxのデフォルトの1つ)、BBR(GoogleのBottleneck Bandwidth and RTT)など。

輻輳制御はRFC 5681などで標準化・推奨事項が示されています。アルゴリズムによりスループットや公平性、ネットワークの振る舞いが変わります。

TCPオプションと拡張

  • MSS(Maximum Segment Size):送信できるデータペイロードの最大値を決める。
  • ウィンドウスケール:受信ウィンドウを拡張するためのビットシフト係数(RFC 1323 / RFC 7323)。
  • タイムスタンプ:RTT推定やPAWS(Protection Against Wrapped Sequence numbers)に使う。
  • SACK:欠損部分を具体的に伝え、効率的再送を可能にする。
  • TCP Fast Openなどの実験的拡張も存在し、接続遅延の低減を図る。

アプリ・OSレベルの振る舞い(Nagle、遅延ACKなど)

Nagleアルゴリズム(RFC 896)は小さなパケットをまとめて送信することでネットワーク負荷を減らしますが、インタラクティブアプリでは遅延を招くことがあります。これを回避するためにTCP_NODELAYソケットオプションを使うことが一般的です。また、遅延ACKは受信側がACKを少し待ってまとめることでトラフィックを減らします(一般に200ms程度が多い)。これらの相互作用により「Nagle + 遅延ACK」が通信遅延を悪化させるケースがあり、アプリ設計やOSチューニングで考慮が必要です。

セキュリティと運用上の注意点

  • SYNフラッド(SYN flood)などのDDoS攻撃対策として、SYN Cookieや接続キューの調整が行われます。
  • ISN(Initial Sequence Number)は予測不能にしてセッションハイジャックを防ぐ(RFC 6528等)。
  • 中間者攻撃や盗聴に対しては、TCP自体は暗号化しないためTLS(例:TLS 1.3 RFC 8446)などを上位層で利用します。
  • NATやファイアウォールはTCPの再キープや接続追跡(stateful inspection)に依存するため、長時間アイドルやパケットロスにより接続が切断されることがある。

デバッグ・解析に使えるツール

  • tcpdump / tshark / Wireshark:パケットキャプチャと解析
  • ss / netstat:ソケットや接続の状態確認
  • iperf / iperf3:スループット測定
  • tc(Linux traffic control):帯域制限や遅延をシミュレーション

実運用でのチューニングと現実的な問題

高帯域・高遅延路(長いRTT)の環境では、十分なウィンドウサイズや適切な輻輳アルゴリズムが重要です。MSSやPMTUD(Path MTU Discovery)で断片化を避けること、RTOや再送のパラメータを適切に設定することが求められます。さらに、ロードバランサやNAT、プロキシを挟む場合は、接続の再利用ポリシーやタイムアウト設定に注意して接続の切断や再試行が過剰にならないよう管理が必要です。

まとめ

TCPはインターネットの基盤を支える重要なプロトコルであり、その設計は信頼性、順序制御、フロー制御、輻輳制御の組み合わせによって成り立っています。仕様(RFC)と実装の双方で多くの拡張・最適化が進められてきました。現代のネットワークで高性能かつ安全な通信を実現するには、TCPの基本動作を理解し、適切なチューニングと上位層(例:TLS)との組合せを検討することが不可欠です。

参考文献