タイトル: TCP
SEOタイトル: TCP 完全ガイド(3ウェイハンドシェイク / コネクション型 / 信頼性 / 輻輳制御 / ヘッダ / UDP との違い)
| この記事の要点 |
|
TCP とは
TCP(Transmission Control Protocol)は、TCP/IP プロトコルスタックのトランスポート層で動作する代表的なプロトコルです。アプリケーション間で仮想的な「通信路(コネクション)」を張り、データを順序通り・欠落なく届けることを保証します。
TCP と UDP の比較
| 項目 | TCP | UDP |
|---|---|---|
| 接続形態 | コネクション型 | コネクションレス型 |
| 信頼性 | あり(再送・順序保証) | なし(欠落・順序逆転OK) |
| 順序保証 | あり | なし |
| フロー制御 | あり(ウィンドウ) | なし |
| 輻輳制御 | あり | なし |
| オーバーヘッド | 大(ヘッダ最小 20 バイト) | 小(ヘッダ 8 バイト) |
| 代表用途 | HTTP/HTTPS / メール / SSH / FTP | DNS / VoIP / 動画ストリーミング / ゲーム |
3 ウェイハンドシェイク(コネクション確立)
クライアントとサーバーは通信開始前に 3 段階のやり取りでコネクションを張ります。
| 段階 | 送信元 | 送信先 | フラグ |
|---|---|---|---|
| 1 | クライアント | サーバー | SYN(seq=x) |
| 2 | サーバー | クライアント | SYN + ACK(seq=y, ack=x+1) |
| 3 | クライアント | サーバー | ACK(ack=y+1) |
これでお互いの初期シーケンス番号を交換し、以後は番号でデータの順序・欠落を判定します。
4 ウェイハンドシェイク(切断)
切断は両方向のFIN / ACKを交わす 4 段階。これにより、片方向だけ閉じる「ハーフクローズ」も表現できます。
- クライアント → サーバー: FIN
- サーバー → クライアント: ACK
- サーバー → クライアント: FIN
- クライアント → サーバー: ACK(TIME_WAIT 後に解放)
TCP ヘッダ構造
| フィールド | サイズ | 意味 |
|---|---|---|
| 送信元ポート / 宛先ポート | 各 16 ビット | アプリケーション識別 |
| シーケンス番号 | 32 ビット | 送信バイトの通し番号 |
| 確認応答番号 | 32 ビット | 次に受信したいバイトの番号 |
| データオフセット | 4 ビット | ヘッダ長(32 ビット単位) |
| 制御フラグ | 各 1 ビット | SYN / ACK / FIN / RST / PSH / URG など |
| ウィンドウサイズ | 16 ビット | 受信可能なバイト数 |
| チェックサム | 16 ビット | 誤り検出 |
| 緊急ポインタ | 16 ビット | URG 時の境界 |
| オプション | 0-40 バイト | MSS / SACK / Window Scale / Timestamp 等 |
信頼性の仕組み
| 仕組み | 概要 |
|---|---|
| シーケンス番号 | 各バイトに通し番号。受信側は順序を復元・重複を排除 |
| 確認応答(ACK) | 受信側が「次にこの番号が欲しい」と通知 |
| 再送タイマー / 高速再送 | ACK が来なければ再送。3 回 Duplicate ACK で即時再送 |
| SACK(Selective ACK) | 飛び飛びの欠落を正確に通知できる拡張 |
| チェックサム | ヘッダ + ペイロードのビット誤り検出 |
フロー制御(ウィンドウ)
受信側のバッファ容量をヘッダのウィンドウサイズで広告し、送信側はそれを超えて送らない仕組みです。大量送信中でも受信側を溢れさせないように制御します。高遅延・高帯域路ではWindow Scaleオプションで上限を 16 ビットを超えて拡張します。
輻輳制御(ネットワーク全体の混雑回避)
ネットワーク全体が詰まらないよう、送信側は輻輳ウィンドウ(cwnd)を管理します。
| 段階 | 動作 |
|---|---|
| スロースタート | cwnd を指数的に増加 |
| 輻輳回避 | 閾値超過後は加算的に増加 |
| パケット喪失検知 | cwnd を縮小(アルゴリズムにより半減等) |
代表アルゴリズム: Reno / NewReno / CUBIC(Linux 既定)/ BBR(Google 提唱)。BBR は喪失ではなく帯域 × RTT を測って制御するため、高 RTT 環境で性能が出やすい。
TCP コネクションの状態遷移
| 状態 | 意味 |
|---|---|
| LISTEN | サーバが接続待ち |
| SYN_SENT | クライアント: SYN 送信済み |
| SYN_RECEIVED | サーバ: SYN+ACK 送信済み |
| ESTABLISHED | 確立済み(データ転送中) |
| FIN_WAIT_1 / 2 | 能動切断側 |
| CLOSE_WAIT | 受動切断側(アプリの close 待ち) |
| TIME_WAIT | 遅延パケット排他のため一定時間待機(通常 2MSL) |
| CLOSED | 解放済み |
ss -tan / netstat -an でこれらの状態を観察できます。大量の TIME_WAIT や CLOSE_WAIT 滞留は典型的な性能問題のシグナルです。
TCP を使う代表的なプロトコル
| 用途 | ポート | プロトコル |
|---|---|---|
| Web | 80 / 443 | HTTP / HTTPS(HTTP/3 は UDP+QUIC) |
| メール送信 | 25 / 587 / 465 | SMTP / SMTPS |
| メール受信 | 110 / 143 / 995 / 993 | POP3 / IMAP(+ TLS) |
| リモート操作 | 22 | SSH |
| ファイル転送 | 20 / 21 | FTP |
| DB | 3306 / 5432 / 1521 など | MySQL / PostgreSQL / Oracle |
TCP/IP モデル内の位置
| 層 | 代表プロトコル |
|---|---|
| アプリケーション層 | HTTP / SMTP / DNS / SSH |
| トランスポート層 | TCP / UDP |
| インターネット層 | IP / ICMP |
| ネットワークインターフェース層 | Ethernet / Wi-Fi |
パフォーマンスに効くチューニングポイント
| 項目 | 内容 |
|---|---|
| MSS / MTU | 1 セグメントの最大バイト。MTU 1500 環境では MSS=1460 が一般的。VPN / トンネル経由ではフラグメント / PMTUD に注意 |
| Window Scale | 高速・高遅延回線では必須。Linux はデフォルトで有効 |
| SACK | 欠落時の再送効率を上げる。両端で有効化 |
| Delayed ACK / Nagle | 小パケット連送を抑制するが、対話アプリでは遅延の原因に。TCP_NODELAY で無効化検討 |
| tcp_tw_reuse / fin_timeout | 大量 TIME_WAIT を再利用する Linux のチューニング |
パケットキャプチャでの観察
tcpdump や Wireshark で TCP の挙動を可視化できます。3 ウェイハンドシェイク失敗、再送、Window 0 通知、RST などの兆候から障害切り分けが可能です。
# 80 番への通信を可視化
sudo tcpdump -i any -nn 'tcp port 80' -c 50
# SYN だけ抽出
sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0' -c 20
# 再送の集計(ss コマンド)
ss -i state established '( dport = :443 or sport = :443 )' | grep -E 'retr|cwnd'
HTTP/2 と HTTP/3 の違い
HTTP/2 までは TCP の上で動きますが、HTTP/3 は UDP の上の QUIC を採用しました。理由は TCP のHoL ブロッキング(1 つのパケット欠落で全ストリームが詰まる)回避と、初回ハンドシェイクの高速化です。とはいえ通常のサーバアプリ・データベース・SSH などは引き続き TCP が主役です。