TCP と UDP の基本 - 3ウェイハンドシェイクと信頼性の仕組みを理解する

TCP と UDP の基本 - 3ウェイハンドシェイクと信頼性の仕組みを理解する

作成日:
読了:18
更新日:
この記事を読む人におすすめPR / Amazonアソシエイト

当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。

Web ページを開くとき、動画を再生するとき、オンラインゲームで対戦するとき。これらはどれもインターネット越しの通信ですが、その足元では性格の異なる2つのプロトコルが使い分けられています。TCP(Transmission Control Protocol)UDP(User Datagram Protocol)です。

この記事では、TCP と UDP の違いを、一次ソースである RFC 9293(TCP、2022年に旧 RFC 793 を置き換えた統合仕様)と RFC 768(UDP)を軸に整理します。TCP の代名詞ともいえる3ウェイハンドシェイク、コネクションの終了と TIME-WAIT、シーケンス番号による信頼性、フロー制御と輻輳制御、そして UDP 上で信頼性を実現する QUIC まで、Web 開発者・インフラ担当者向けに一通り押さえます。

TCP/IP の層と、その中での TCP・UDP の位置づけ

インターネットの通信は、役割ごとに層(レイヤー)を分けて設計されています。ざっくり4つの層で考えると、TCP と UDP がどこにいるのかが見えてきます。

役割代表的なプロトコル
アプリケーション層アプリ固有のやり取りHTTP、DNS、SMTP
トランスポート層端末上のプログラム間で届けるTCPUDP
インターネット層宛先ホストまで届けるIP(IPv4 / IPv6)
リンク層隣の機器へ物理的に届けるEthernet、Wi-Fi

IP は「ホストからホストへパケットを届ける」ことは担いますが、途中でパケットが失われたり、順序が入れ替わったりする可能性があります。IP 自身は、それを直す責任を持ちません。

そこで登場するのがトランスポート層です。TCP と UDP はどちらもポート番号を使って、1台のホスト上で動く複数のプログラム(Web サーバー、メールサーバーなど)のうち、どれ宛ての通信かを区別します。RFC 9293 も「TCP はポート番号を使ってアプリケーションサービスを識別し、ホスト間の個別のフローを多重化する」と述べています。TCP と UDP の決定的な違いは、この上に信頼性を積むかどうかです。

UDP: 最小限の仕組みで速く送る

まずシンプルな UDP から見ます。UDP は RFC 768(J. Postel、1980年8月)で定義された、非常に小さなプロトコルです。RFC 768 は UDP を「アプリケーションプログラムが最小限のプロトコル機構でメッセージを送るための手続き」と表現しています。

UDP の特徴は、裏を返せば「やらないこと」の多さです。

  • コネクションレス: 事前のやり取り(ハンドシェイク)なしに、いきなりデータグラムを送る
  • 到達保証なし: RFC 768 は「配送と重複防止は保証されない(delivery and duplicate protection are not guaranteed)」と明記している
  • 順序保証なし: 届いた順番が送った順番と一致するとは限らない
  • 再送なし・フロー制御なし・輻輳制御なし: 失われても知らせず、送信ペースの調整もしない

そのぶんヘッダは非常に軽量です。UDP のヘッダはわずか8バイトで、4つの16ビットフィールドだけを持ちます。

フィールド内容
送信元ポート(Source Port)応答先のポート。任意(0 も可)
宛先ポート(Destination Port)宛先アプリケーションのポート
長さ(Length)ヘッダ+データの長さ。最小は8オクテット
チェックサム(Checksum)誤り検出用。IPv4 では任意

チェックサムは16ビットの1の補数和で計算し、IPv4 では送っても送らなくてもよい任意項目です。RFC 768 は「送信側がチェックサムを生成しなかった場合は、全ビット0を送る」と定めています。

「保証しない」ことは弱点にも見えますが、速さと軽さという強みでもあります。1往復のハンドシェイクも、再送待ちもないため、遅延に敏感な用途に向きます。DNS の問い合わせ、音声・映像のストリーミング、オンラインゲーム、NTP による時刻同期などが代表例です。DNS が UDP を基本に使う背景は、DNS の仕組み入門 でも触れています。

TCP: 信頼性を積み上げる

一方の TCP は、RFC 9293 の言葉を借りれば「アプリケーションに対して信頼性のある、順序どおりの、バイトストリームサービスを提供する(reliable, in-order, byte-stream service)」プロトコルです。UDP が「送りっぱなし」なのに対し、TCP は次のような仕組みで信頼性を作り込んでいます。

  • シーケンス番号: 送るデータの1オクテットごとに番号を振り、順序を管理する
  • 確認応答(ACK): 受け取った側が「ここまで受け取った」と返す
  • 再送: 一定時間 ACK が返らなければ、送り直す
  • フロー制御: 受信側の処理能力を超えないよう、送信量を調整する
  • 輻輳制御: ネットワークの混雑に応じて、送信ペースを加減する

確認応答は累積的(cumulative)です。RFC 9293 は「シーケンス番号 X の確認応答は、X より前(X を含まない)のすべてのオクテットを受信したことを示す」と説明しています。つまり ACK 番号は「次に受け取りたいオクテットの番号」を表します。

TCP のヘッダは UDP より豊かで、最小でも20バイトあります。送信元・宛先ポート、シーケンス番号(32ビット)、確認応答番号(32ビット)、データオフセット、各種制御フラグ(SYN、ACK、FIN、RST、PSH、URG など)、ウィンドウ、チェックサム、緊急ポインタなどを持ちます。なお TCP のチェックサムは UDP と違い省略できません。RFC 9293 は「TCP チェックサムは決して任意ではない。送信側は必ず生成し、受信側は必ず検査しなければならない」と明言しています。

NOTE

TCP が扱うのは「メッセージの列」ではなく、切れ目のないバイトストリームです。アプリが send() した区切りは保存されず、受信側では複数の送信がまとまって届いたり(結合)、1回の送信が分割されて届いたりします。メッセージ境界が必要なら、アプリ側のプロトコルで長さやデリミタを決める必要があります。

3ウェイハンドシェイク: コネクションを開く

TCP は通信を始める前に、まず両者でコネクションを確立します。この手順が有名な3ウェイハンドシェイク(3-way handshake、3WHS)です。目的は、RFC 9293 の言葉では「各側が自分の初期シーケンス番号を送り、それが相手から確認応答されるのを受け取る」ことにあります。互いの開始番号をすり合わせる儀式、と考えると分かりやすいです。

Loading diagram...

流れは次の3段です。

  1. SYN: クライアントが SYN フラグを立て、自分の初期シーケンス番号 x を送る
  2. SYN-ACK: サーバーが SYN と ACK を同時に立て、自分の初期番号 y を送りつつ、x+1 で相手の SYN を確認する
  3. ACK: クライアントが y+1 でサーバーの SYN を確認する

この3往復(正確には2往復半)で、両者は互いの初期シーケンス番号を確認し合い、ESTABLISHED(確立済み)状態に入ります。ここでようやくデータのやり取りが始まります。UDP がハンドシェイクなしにいきなり送るのと対照的に、TCP はこの1往復半のコストを先に払って信頼性の土台を作るわけです。

初期シーケンス番号を毎回0から始めず、ある値から始める理由の1つは、古いコネクションの残存パケットとの混同や、なりすましを避けるためです。RFC 9293 でも初期シーケンス番号の選び方が詳しく規定されています。

コネクションの状態遷移

TCP コネクションは、確立から終了まで状態機械(ステートマシン)として管理されます。RFC 9293 は次の11個の状態を定義しています。

LISTENSYN-SENTSYN-RECEIVEDESTABLISHEDFIN-WAIT-1FIN-WAIT-2CLOSE-WAITCLOSINGLAST-ACKTIME-WAITCLOSED です。

サーバーは LISTEN で待ち受け、SYN を受けると SYN-RECEIVED へ移り、ACK を受けて ESTABLISHED に至ります。netstatss コマンドでソケットの状態を見ると、これらの名前がそのまま並んでいるのが分かります。

コネクションの終了と TIME-WAIT

コネクションを閉じるときは、FIN(finish)フラグを使います。TCP は全二重(双方向)なので、各方向を独立に閉じます。結果として、開くときの3ウェイに対し、閉じるときは4ウェイになるのが基本形です。

Loading diagram...

RFC 9293 は「相手側の TCP が FIN を確認応答し、かつ自分の FIN を送り終えたら、最初の TCP はその FIN を ACK できる」と説明しています。片方が FIN を送っても、もう片方はまだデータを送り続けられる(ハーフクローズ)点がポイントです。

終了時に特徴的なのが TIME-WAIT 状態です。能動的に閉じた側は、すぐには CLOSED にならず、しばらく TIME-WAIT にとどまります。RFC 9293 は「コネクションを能動的にクローズした場合、TIME-WAIT 状態に 2×MSL(Maximum Segment Lifetime)の時間だけとどまらなければならない」と定めています。MSL は同 RFC で2分とされているため、2×MSL は理屈上4分です。

NOTE

TIME-WAIT が存在するのは、最後の ACK が失われても相手の FIN 再送に応答できるようにし、さらに古いコネクションの遅延パケットが、同じポート組で開いた新しいコネクションに紛れ込むのを防ぐためです。サーバーで TIME-WAIT が大量に積み上がるのは、多くの接続を能動的に閉じている裏返しでもあります。

フロー制御と輻輳制御

TCP が「相手やネットワークを溢れさせない」ために持つのが、フロー制御と輻輳制御です。似ていますが守る対象が違います。

フロー制御は、受信側の処理能力を超えないようにする仕組みです。TCP ヘッダのウィンドウ(window)フィールドで、受信側が「いまどれだけ受け取れるか」を送信側に伝えます。RFC 9293 はウィンドウを「確認応答フィールドが示すオクテットから始めて、このセグメントの送信者が受け入れる用意があるデータオクテット数」と定義しています。受信側のバッファが埋まればウィンドウは小さくなり、送信側はそのぶんペースを落とします。ウィンドウ値は符号なしとして扱う必要がある、とも規定されています。

輻輳制御は、受信側ではなくネットワーク全体の混雑を避ける仕組みです。こちらは TCP のヘッダに直接のフィールドがあるわけではなく、送信側が内部に輻輳ウィンドウを持ってペースを加減します。代表的なアルゴリズムは RFC 5681(2009年)にまとまっており、次の4つが柱です。

  • スロースタート: 最初は小さく送り、ACK が返るたびに送信量を指数的に増やす
  • 輻輳回避: ある閾値を超えたら、増やし方を緩やかにする
  • ファストリトランスミット: 重複 ACK を手がかりに、タイムアウトを待たず素早く再送する
  • ファストリカバリ: 再送後、送信量をゼロに戻さず控えめに回復する

実際の送信量は「フロー制御のウィンドウ」と「輻輳ウィンドウ」の小さいほうで決まります。受信側の余裕とネットワークの余裕、どちらか厳しいほうに合わせる、というわけです。この「混雑に応じて流量を絞る」考え方は、アプリ層で流量を制限するレート制限アルゴリズム とも通じるものがあります。

TCP と UDP の使い分け

ここまでの違いを表で整理します。

観点TCPUDP
コネクションあり(3ウェイハンドシェイク)なし(送りっぱなし)
到達保証あり(ACK と再送)なし
順序保証ありなし
フロー制御・輻輳制御ありなし
ヘッダサイズ最小20バイト8バイト
速度・遅延相対的に重い軽い・低遅延
主な定義RFC 9293RFC 768
向く用途Web、メール、ファイル転送DNS、音声・映像、ゲーム、NTP

選ぶ基準はシンプルです。データが欠けたり順序が乱れたりして困るなら TCP、多少欠けても速さや低遅延が優先なら UDP、が出発点です。Web で使う代表的なポート番号も押さえておくと、実務で役立ちます。

プロトコルポートトランスポート
HTTP80TCP
HTTPS443TCP(HTTP/3 は UDP)
SSH22TCP
DNS53UDP / TCP
NTP123UDP

QUIC: UDP の上に信頼性を作り直す

「TCP は信頼性、UDP は速さ」という対比は基本ですが、近年はその境界を塗り替える動きがあります。それが QUIC です。QUIC は RFC 9000(2021年)で標準化された「UDP ベースの多重化された安全なトランスポート(A UDP-Based Multiplexed and Secure Transport)」です。

一見すると矛盾して見えます。信頼性のない UDP の上に、なぜ信頼性を載せるのでしょうか。理由は、TCP がカーネルや中継機器に深く根付いていて改良しづらい一方、UDP の上ならアプリケーション側で自由に新しい輸送方式を作れるからです。QUIC は UDP を土台にしつつ、TCP に相当する再送や順序保証、フロー制御を自前で実装します。

QUIC の特徴は次のとおりです。

  • 低遅延な接続確立: TLS 1.3 の暗号ネゴシエーションをハンドシェイクに統合し、接続開始を速くする
  • ストリーム多重化とヘッドオブラインブロッキングの回避: 複数ストリームを並行して流し、片方のパケット損失が他方をブロックしない
  • 標準で暗号化: 通信の秘匿性・完全性を組み込みで備える

TCP では、1本のコネクション上で複数のリクエストを多重化すると、途中の1パケット損失が後続すべてを止めてしまう問題(ヘッドオブラインブロッキング)がありました。QUIC はストリームごとに独立に扱うことでこれを解消します。この QUIC の上で動くのが HTTP/3 で、HTTPS が UDP の443番ポートを使う場面が増えているのは、この流れによるものです。ブラウザとサーバー間のリアルタイム通信の選択肢を整理したWebSocket / SSE / ポーリングの比較 も、あわせて読むと通信レイヤーの見取り図がつかめます。

まとめ

  • トランスポート層には性格の異なる2つがある。TCP(RFC 9293)は信頼性・順序保証ありUDP(RFC 768)は軽量・低遅延で保証なし。どちらもポート番号でアプリを多重化する
  • TCP は3ウェイハンドシェイク(SYN / SYN-ACK / ACK)で互いの初期シーケンス番号を確認し合い、ESTABLISHED になってから通信する
  • 信頼性はシーケンス番号・累積 ACK・再送で作る。終了は FIN による4ウェイで、能動クローズ側はTIME-WAIT(2×MSL)にとどまる
  • 流量はフロー制御(ウィンドウ)輻輳制御(RFC 5681)の小さいほうで決まる。前者は受信側、後者はネットワークの混雑を守る
  • UDP の上に信頼性と多重化を作り直したのが QUIC(RFC 9000)。HTTP/3 の土台として、Web の通信を静かに置き換えつつある

TCP と UDP の違いは、突き詰めれば「信頼性のコストを、いつ・誰が払うか」の設計判断です。この土台が分かると、DNS がなぜ UDP なのか、HTTP/3 がなぜ UDP に戻ったのか、といった一段上の話も自然につながって見えてきます。

参考リンク

TLS 1.3 と HTTPS ハンドシェイクの仕組み - 1-RTT・前方秘匿性・0-RTTを一次ソースで理解する

TLS 1.3 と HTTPS ハンドシェイクの仕組み - 1-RTT・前方秘匿性・0-RTTを一次ソースで理解する

16

HTTPS の土台である TLS 1.3 のハンドシェイクを、一次ソースの RFC 8446 を軸に整理します。ClientHello から Finished までのメッセージの役割、ECDHE による鍵共有と前方秘匿性、TLS 1.2(RFC 5246)との違い(2-RTT から 1-RTT へ、静的 RSA 鍵交換の廃止、暗号スイートの簡素化)、0-RTT / early data の再送リスク、PSK によるセッション再開、そして OpenSSL や curl での確認方法まで、Web 開発者・インフラ担当者向けにまとめます。

HTTP/3 と QUIC 入門 - なぜ HTTP は TCP を捨てて UDP に移ったのか

HTTP/3 と QUIC 入門 - なぜ HTTP は TCP を捨てて UDP に移ったのか

19

HTTP/3 と、その土台となる新トランスポート QUIC を、一次ソースの RFC を軸に入門解説します。HTTP/2 が抱える TCP 上の Head-of-Line ブロッキング問題から出発し、QUIC が UDP の上でストリーム多重化・TLS 1.3 統合・0-RTT/1-RTT ハンドシェイク・Connection ID によるコネクションマイグレーションをどう実現するのかを直感的に整理。RFC 9000/9001/9002/9114/9204 の対応や、ブラウザ・サーバー・CDN の対応状況、curl や DevTools での確認方法、注意点とトレードオフまで Web 開発者向けにまとめます。

DNS の仕組み入門 - 名前解決・レコード種別・TTL とキャッシュを理解する

DNS の仕組み入門 - 名前解決・レコード種別・TTL とキャッシュを理解する

23

DNS(ドメインネームシステム)の名前解決の仕組みを、一次ソースである RFC を軸に整理します。ルート・TLD・権威サーバーの階層、再帰リゾルバとスタブリゾルバ、A/AAAA/CNAME/MX/NS/SOA/TXT/CAA/SRV/PTR などのレコード種別、再帰と反復の解決の流れ、TTL とキャッシュ、ネガティブキャッシュ(RFC 2308)、ポート53と UDP/TCP・EDNS0(RFC 6891)、DNSSEC(RFC 4033)、DoH(RFC 8484)/DoT(RFC 7858)まで、Web 開発者・インフラ担当者向けにまとめます。