インターネット上でデータをやり取りする際、アプリケーション間の通信を担うのがトランスポート層です。このトランスポート層には、TCP(Transmission Control Protocol)とUDP(User Datagram Protocol)という2つの主要なプロトコルがあります。

TCPとUDPはどちらもIP上で動作しますが、信頼性と速度のトレードオフにおいて対照的な特徴を持ちます。この違いを正しく理解することは、適切な通信プロトコルを選択し、アプリケーションのパフォーマンスを最適化する上で非常に重要です。

本記事では、TCPとUDPの違いについて以下の内容を解説します。

  • TCPの信頼性を実現する仕組み(3ウェイハンドシェイク、再送制御、フロー制御、輻輳制御)
  • UDPの軽量でシンプルな通信モデル
  • TCPヘッダとUDPヘッダの構造比較
  • それぞれのプロトコルが適したユースケース
  • 実際のネットワークコマンドでの確認方法

この記事を読むことで、TCPとUDPの特性を理解し、用途に応じたプロトコル選択ができるようになります。

前提条件

本記事を理解するために、以下の知識があることを前提としています。

  • OSI参照モデルの第4層(トランスポート層)の役割を把握している
  • IPアドレスとパケット通信の基本概念を理解している
  • ポート番号の役割について基礎的な知識がある

実行環境

ネットワーク通信の確認には以下の環境を使用します。

OS 確認コマンド
Windows 10/11 netstat -anTest-NetConnection
macOS netstat -annc(netcat)
Linux ss -tulnnc(netcat)

特別なソフトウェアのインストールは不要です。

期待される学習成果

本記事を読み終えると、以下のことができるようになります。

  1. TCPとUDPの根本的な違いを説明できる
  2. TCPの3ウェイハンドシェイクの流れを図解できる
  3. 再送制御、フロー制御、輻輳制御の役割を理解できる
  4. アプリケーションの要件に応じてTCPかUDPを適切に選択できる
  5. ネットワークコマンドでTCP/UDP通信の状態を確認できる

トランスポート層の役割

OSI参照モデルにおいて、トランスポート層(第4層)はアプリケーション間の通信を担当します。ネットワーク層(第3層)がホスト間のパケット転送を担うのに対し、トランスポート層は以下の役割を果たします。

  1. エンドツーエンドの通信: 送信元アプリケーションから宛先アプリケーションへのデータ配送
  2. 多重化と分離: ポート番号を使用して、同一ホスト上の複数アプリケーションを識別
  3. データの整合性: チェックサムによるエラー検出

以下の図は、ネットワーク層とトランスポート層の関係を示しています。

flowchart TB
    subgraph "送信側ホスト"
        A1[アプリケーションA<br/>ポート80]
        A2[アプリケーションB<br/>ポート443]
        T1[トランスポート層<br/>TCP/UDP]
        N1[ネットワーク層<br/>IP]
    end
    
    subgraph "受信側ホスト"
        A3[アプリケーションA<br/>ポート80]
        A4[アプリケーションB<br/>ポート443]
        T2[トランスポート層<br/>TCP/UDP]
        N2[ネットワーク層<br/>IP]
    end
    
    A1 & A2 --> T1
    T1 --> N1
    N1 -.->|パケット転送| N2
    N2 --> T2
    T2 --> A3 & A4

ネットワーク層のIPはベストエフォート型のプロトコルであり、パケットの到達保証やデータの順序保証を行いません。これらの機能を必要に応じて提供するのがトランスポート層の役割であり、TCPとUDPは異なるアプローチでこの課題に対処します。

TCPの特徴と信頼性機能

TCP(Transmission Control Protocol)は、RFC 9293で規定されているコネクション型のプロトコルです。「信頼性のある、順序付けられたバイトストリームサービス」をアプリケーションに提供します。

TCPの主な特徴

TCPは以下の特徴を持つプロトコルです。

特徴 説明
コネクション型 通信前に接続を確立し、終了時に切断する
信頼性保証 パケットロスを検出し、再送により確実に配送する
順序保証 シーケンス番号により、データを送信順に再構成する
フロー制御 受信側の処理能力に合わせて送信速度を調整する
輻輳制御 ネットワークの混雑状況に応じて送信レートを制御する

これらの機能により、TCPは信頼性が必要なアプリケーション通信に広く使用されています。

TCPヘッダの構造

TCPセグメントのヘッダは最小20バイトで、以下の情報を含みます。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          送信元ポート         |          宛先ポート           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      シーケンス番号                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      確認応答番号                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|データ |       |C|E|U|A|P|R|S|F|                               |
|オフセット| 予約  |W|C|R|C|S|S|Y|I|         ウィンドウサイズ       |
|     |       |R|E|G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          チェックサム         |        緊急ポインタ           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    オプション(可変長)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

各フィールドの役割は以下の通りです。

フィールド サイズ 役割
送信元ポート 16ビット 送信側アプリケーションを識別
宛先ポート 16ビット 受信側アプリケーションを識別
シーケンス番号 32ビット このセグメントの最初のデータバイトの番号
確認応答番号 32ビット 次に受信を期待するバイトの番号
制御フラグ 各1ビット SYN、ACK、FIN、RSTなどの制御情報
ウィンドウサイズ 16ビット 受信可能なデータ量を通知
チェックサム 16ビット データの整合性検証

3ウェイハンドシェイク

TCPでは通信開始前に、3ウェイハンドシェイク(3-Way Handshake)と呼ばれる手順でコネクションを確立します。この手順により、両端が通信の準備ができていることを相互に確認します。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    
    Note over C: CLOSED
    Note over S: LISTEN
    
    C->>S: SYN (seq=x)
    Note over C: SYN-SENT
    Note over S: SYN-RECEIVED
    
    S->>C: SYN+ACK (seq=y, ack=x+1)
    Note over C: ESTABLISHED
    
    C->>S: ACK (seq=x+1, ack=y+1)
    Note over S: ESTABLISHED
    
    Note over C,S: データ通信開始

各ステップの詳細は以下の通りです。

  1. SYN(同期): クライアントが接続要求を送信し、初期シーケンス番号(ISN)を提示
  2. SYN+ACK: サーバーが接続を承認し、自身の初期シーケンス番号を返送
  3. ACK(確認応答): クライアントが最終確認を送信し、コネクション確立が完了

この3段階の手順が必要な理由は、シーケンス番号がグローバルなクロックに基づいていないためです。古い重複したSYNセグメントと新しい接続要求を区別するために、相互確認のプロセスが必要です。

再送制御(Retransmission)

TCPはパケットロスを検出し、自動的に再送を行うことで信頼性を保証します。

sequenceDiagram
    participant C as 送信側
    participant S as 受信側
    
    C->>S: セグメント1 (seq=100)
    S->>C: ACK (ack=200)
    
    C-xS: セグメント2 (seq=200) 損失
    Note over C: タイムアウト発生
    
    C->>S: セグメント2 再送 (seq=200)
    S->>C: ACK (ack=300)
    
    Note over C,S: 通信継続

再送制御の主な仕組みは以下の通りです。

  1. タイムアウトベースの再送: 一定時間内にACKが返らない場合に再送
  2. RTO(Retransmission Timeout)の動的計算: ネットワーク状況に応じてタイムアウト値を調整
  3. 高速再送: 重複ACKを3回受信した場合、タイムアウトを待たずに再送

RFC 6298で規定されているRTOの計算では、RTT(Round Trip Time)のサンプルを測定し、平滑化された推定値を維持します。

フロー制御(Flow Control)

フロー制御は、受信側の処理能力を超えてデータが送られることを防ぐ仕組みです。TCPはスライディングウィンドウ方式を採用しています。

flowchart LR
    subgraph "送信側バッファ"
        direction LR
        A1[送信済<br/>ACK待ち]
        A2[送信可能<br/>ウィンドウ内]
        A3[送信待ち<br/>ウィンドウ外]
    end
    
    subgraph "受信側バッファ"
        direction LR
        B1[受信済<br/>処理待ち]
        B2[受信可能<br/>空き領域]
    end
    
    A2 -->|データ送信| B2
    B1 -->|ウィンドウサイズ通知| A2

受信側は、自身のバッファの空き容量をウィンドウサイズとしてTCPヘッダに含めて通知します。送信側はこのウィンドウサイズを超えてデータを送信しません。

ウィンドウがゼロになった場合(ゼロウィンドウ状態)、送信側は定期的にプローブセグメントを送信して、ウィンドウの再開を確認します。

輻輳制御(Congestion Control)

輻輳制御は、ネットワークの混雑を検出し、送信レートを調整してネットワーク全体のパフォーマンスを維持する仕組みです。

RFC 5681で規定されている基本的な輻輳制御アルゴリズムは以下の通りです。

アルゴリズム 動作
スロースタート 接続開始時に輻輳ウィンドウを指数的に増加
輻輳回避 閾値到達後に線形的に増加
高速再送 3重複ACKでパケットロスを検出
高速回復 高速再送後に輻輳ウィンドウを半減して再開
flowchart TB
    subgraph "輻輳制御の状態遷移"
        A[スロースタート] -->|cwnd >= ssthresh| B[輻輳回避]
        A -->|3重複ACK| C[高速再送/回復]
        B -->|3重複ACK| C
        A -->|タイムアウト| A
        B -->|タイムアウト| A
        C -->|回復完了| B
    end

輻輳ウィンドウ(cwnd)は送信側が管理する仮想的なウィンドウであり、実際に送信できるデータ量はmin(cwnd, rwnd)(rwndは受信側のウィンドウサイズ)となります。

コネクション終了(4ウェイハンドシェイク)

TCPコネクションの終了は、4ウェイハンドシェイクで行われます。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    
    Note over C: ESTABLISHED
    Note over S: ESTABLISHED
    
    C->>S: FIN (seq=u)
    Note over C: FIN-WAIT-1
    
    S->>C: ACK (ack=u+1)
    Note over C: FIN-WAIT-2
    Note over S: CLOSE-WAIT
    
    S->>C: FIN (seq=v)
    Note over S: LAST-ACK
    
    C->>S: ACK (ack=v+1)
    Note over C: TIME-WAIT
    Note over S: CLOSED
    
    Note over C: 2MSL待機後
    Note over C: CLOSED

TIME-WAIT状態は2MSL(Maximum Segment Lifetime、通常4分)間維持されます。これにより、遅延した古いセグメントがネットワークから消えるのを待ち、新しい接続との混同を防ぎます。

UDPの特徴とシンプルな通信モデル

UDP(User Datagram Protocol)は、RFC 768で規定されているコネクションレス型のプロトコルです。最小限のオーバーヘッドで高速な通信を実現します。

UDPの主な特徴

UDPはTCPと対照的な特徴を持ちます。

特徴 説明
コネクションレス型 事前の接続確立なしにデータを送信
信頼性なし パケットロスの検出や再送を行わない
順序保証なし パケットの到着順序を保証しない
軽量 ヘッダサイズが8バイトと小さい
低遅延 ハンドシェイクや確認応答のオーバーヘッドがない

UDPヘッダの構造

UDPデータグラムのヘッダは8バイトのみで、非常にシンプルな構造です。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          送信元ポート         |          宛先ポート           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            長さ               |          チェックサム         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
フィールド サイズ 役割
送信元ポート 16ビット 送信側アプリケーションを識別(省略可能)
宛先ポート 16ビット 受信側アプリケーションを識別
長さ 16ビット ヘッダとデータの合計長
チェックサム 16ビット データの整合性検証(IPv4では省略可能)

UDPの通信フロー

UDPはコネクションレスのため、データを即座に送信できます。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    
    Note over C,S: 接続確立なし
    
    C->>S: データグラム1
    C->>S: データグラム2
    C->>S: データグラム3
    
    Note over C,S: ACKなし、再送なし

UDPでは以下のことが発生する可能性があります。

  • パケットが到達しない(ロス)
  • パケットが順番通りに届かない(順序逆転)
  • パケットが重複して届く(重複)

これらの問題に対処が必要な場合は、アプリケーション層で対応する必要があります。

TCPとUDPの比較

TCPとUDPの主な違いを表にまとめます。

項目 TCP UDP
接続 コネクション型 コネクションレス型
信頼性 保証あり(再送制御) 保証なし
順序保証 あり(シーケンス番号) なし
フロー制御 あり(スライディングウィンドウ) なし
輻輳制御 あり なし
ヘッダサイズ 20~60バイト 8バイト
速度 比較的低速(オーバーヘッドあり) 高速(低オーバーヘッド)
通信形態 ユニキャスト ユニキャスト、マルチキャスト、ブロードキャスト
flowchart TB
    subgraph "TCP"
        direction TB
        T1[コネクション確立] --> T2[データ転送<br/>確認応答あり]
        T2 --> T3[コネクション切断]
        T2 -.->|再送| T2
    end
    
    subgraph "UDP"
        direction TB
        U1[データグラム送信] --> U2[データグラム送信]
        U2 --> U3[データグラム送信]
    end

TCPとUDPのユースケース

それぞれのプロトコルは、特性に応じた適切なユースケースがあります。

TCPが適したユースケース

信頼性が重要で、データの欠落や順序の入れ替わりが許容されない場合に使用します。

プロトコル/アプリケーション ポート番号 理由
HTTP/HTTPS 80/443 Webページの完全な転送が必要
FTP 20/21 ファイルの完全性が重要
SMTP 25 メールデータの欠落は許容されない
SSH 22 コマンドの確実な実行が必要
データベース接続 様々 トランザクションの整合性が重要

UDPが適したユースケース

速度や低遅延が重要で、一部のデータ損失が許容される場合に使用します。

プロトコル/アプリケーション ポート番号 理由
DNS 53 小さなクエリで再送オーバーヘッドを避ける
DHCP 67/68 ブロードキャスト通信が必要
NTP 123 時刻同期は最新値が重要
VoIP(音声通話) 様々 リアルタイム性が重要、古いデータは不要
オンラインゲーム 様々 低遅延が重要、位置情報は最新値のみ必要
ストリーミング 様々 遅延より継続再生が重要

プロトコル選択のフローチャート

flowchart TD
    A[通信要件の分析] --> B{データの完全性が必須?}
    B -->|はい| C{順序保証が必要?}
    B -->|いいえ| D{リアルタイム性が重要?}
    
    C -->|はい| E[TCP]
    C -->|いいえ| F{アプリ層で対応可能?}
    
    D -->|はい| G[UDP]
    D -->|いいえ| H{低オーバーヘッドが重要?}
    
    F -->|はい| G
    F -->|いいえ| E
    
    H -->|はい| G
    H -->|いいえ| E

QUICプロトコルについて

近年、GoogleがHTTP/3で採用したQUICプロトコルが注目されています。QUICはUDP上に構築されたプロトコルで、TCPの信頼性機能とUDPの低遅延を組み合わせた特徴を持ちます。

特徴 説明
UDP上で動作 ファイアウォールやNATを通過しやすい
TLS 1.3統合 暗号化が組み込まれ、ハンドシェイクが高速
マルチストリーム Head-of-Line Blockingを回避
接続マイグレーション IPアドレス変更時も接続を維持

QUICの詳細についてはRFC 9000を参照してください。

ネットワークコマンドでTCP/UDP通信を確認する

実際の環境でTCPとUDP通信の状態を確認する方法を紹介します。

Windowsでの確認

TCP接続とUDPポートの一覧を確認します。

1
2
3
4
5
6
7
8
# すべてのTCP/UDP接続を表示
netstat -an

# TCPのみ表示(リスニングポート)
netstat -an | findstr "TCP.*LISTENING"

# 特定ポートの確認(例:443)
netstat -an | findstr ":443"

出力例:

Proto  Local Address          Foreign Address        State
TCP    0.0.0.0:443           0.0.0.0:0              LISTENING
TCP    192.168.1.10:52341    93.184.216.34:443      ESTABLISHED
UDP    0.0.0.0:53            *:*

TCPではState列でコネクションの状態を確認できます。

状態 説明
LISTENING 接続待ち受け中
ESTABLISHED 接続確立済み
TIME_WAIT 切断後の待機中
CLOSE_WAIT 相手からのFIN受信済み

Linux/macOSでの確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# ssコマンドでTCP接続を確認(Linux)
ss -tuln

# netstatでTCP/UDP確認(macOS/Linux)
netstat -an | grep -E "^(tcp|udp)"

# 特定ポートへのTCP接続テスト
nc -zv example.com 443

# UDP接続テスト
nc -zuv example.com 53

tcpdumpでパケットをキャプチャ

より詳細な通信内容を確認する場合は、tcpdumpを使用します。

1
2
3
4
5
6
7
8
# TCPの3ウェイハンドシェイクを観察
sudo tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' -n

# 特定ポートのTCP通信
sudo tcpdump -i eth0 port 443 -n

# UDP通信の確認
sudo tcpdump -i eth0 udp port 53 -n

まとめ

本記事では、TCPとUDPの違いについて解説しました。

TCPの特徴

  • コネクション型プロトコルで、3ウェイハンドシェイクにより接続を確立
  • 再送制御、フロー制御、輻輳制御により信頼性のある通信を実現
  • オーバーヘッドがあるため、UDPより遅延が大きい
  • Webアクセス、ファイル転送、メールなど信頼性が重要な用途に適する

UDPの特徴

  • コネクションレス型プロトコルで、即座にデータを送信可能
  • 信頼性機能がなく、軽量で低遅延
  • ヘッダサイズは8バイトのみ
  • リアルタイム通信、DNS、ストリーミングなど速度重視の用途に適する

適切なプロトコルを選択するには、アプリケーションの要件(信頼性、遅延、帯域効率など)を正確に理解することが重要です。

次回の記事では、ポート番号とソケット通信について詳しく解説し、アプリケーション間通信の識別方法を学びます。

参考リンク