NET // communication networks
LESSON 12 / 標準編

アプリ層 ─ HTTP/1.1 と HTTP/2 詳細

Web の通信を支える HTTP プロトコルを大学授業レベルで掘り下げます。リクエスト/レスポンスの厳密な構造、主要メソッド、ステータスコード、頻出ヘッダ、Cookie によるステート管理、パーシステント接続、そして HTTP/2 が導入したバイナリフレーミング・ストリーム多重化・HPACK までを体系的に整理します。

学習目標

本講を終えると、以下を達成できるようになります。

本講は 第3回 プロトコルとTCP/IP階層モデル(基礎) および 第6回 HTTP/Webの基本(基礎) の発展回です。基礎編では「HTTP は Web ページを取りに行くための約束」として導入しましたが、本講ではメッセージのバイト列レベルでの形と、バージョンごとの設計判断を扱います。HTTP/3(QUIC) の詳細は 発展編 で扱います。HTTPS(HTTP over TLS)の詳細 は TLS の前提が要るため、第35回 TLS/PKI第36回 アプリ層プロトコルのセキュア化 でまとめて扱います。

このレッスンの目次

01 HTTPの役割 HTTP(HyperText Transfer Protocol) は、Web ブラ… 02 メッセージ構造 HTTP/1.x のメッセージは テキスト行 で構成されます。リクエストもレスポンス… 03 主要メソッド HTTP リクエストの先頭にある メソッド(method) は、サーバに対して 「何… 04 ステータスコード レスポンスの 3桁の数値 がステータスコードです。先頭の桁で大分類が決まり、5つのカ… 05 主要ヘッダ HTTP メッセージのヘッダは 「フィールド名: 値」 の形式で、リクエストとレスポ… 06 ステートレスとCookie HTTP は設計上 ステートレス(stateless) なプロトコルです。つまりサー… 07 パーシステント接続 Web ページは通常、HTML 1つだけでなく、画像・CSS・JS など 多数のオブ… 08 HTTP/2の改善 HTTP/2(RFC 9113、当初 RFC 7540) は セマンティクス(メソッ… 09 HOLとHTTP/3への動機 HTTP/2 でアプリ層の HOL は解決しましたが、 下層 TCP の HOL ブ… 10 まとめと用語 本講の重要語句を整理 11 確認問題 理解度を問題でチェック

HTTP の役割を再確認する

HTTP(HyperText Transfer Protocol) は、Web ブラウザ(クライアント) と Web サーバの間で リソース(HTML / 画像 / JSON など) をやり取りするためのアプリケーション層プロトコルです。トランスポート層には基本的に TCP(ポート 80) を使い、HTTPS の場合は TLS の上で動きます(TLS は通常 TCP ポート 443)。クライアントが要求(リクエスト)を出し、サーバが応答(レスポンス)を返す という 要求応答(request-response) 型のやり取りで進みます。
POINT HTTP の本質は 「テキストベースの命令(リクエスト)に、テキストベースの回答(レスポンス)を返す」 という単純な約束。HTTP/1.x まではメッセージはほぼ人間が読める ASCII 文字列で、HTTP/2 以降はバイナリフレームになります。

クライアント-サーバ型の相互作用

Web ブラウザ (HTTP クライアント) Web サーバ (Apache / Nginx 等, ポート80) HTTP リクエスト(GET / POST など) HTTP レスポンス(ステータス + 本文) 下層では TCP の通信路が先に用意されている前提

図の見方:HTTP は常にクライアントが先に話しかける(プル型)。サーバから能動的に「ねえねえ」とは話しかけません(HTTP/2 のサーバプッシュは例外的機能で、後述)。

RFC で定義された世界中の標準

HTTP の仕様は IETF の RFC(Request for Comments) として公開されています。主要な版だけを挙げると、HTTP/1.1 は RFC 9110(Semantics)・RFC 9112(HTTP/1.1)、HTTP/2 は RFC 9113、HTTP/3 は RFC 9114 で標準化されています。誰もが同じ仕様を読める からこそ、世界中のブラウザとサーバが相互運用できます。

つながる知識: 「ポート 80 / 443 で Listen するサーバ」「Socket API で TCP に書き込む」という見方は、基礎 第3回 のトランスポート層の話と直結しています。HTTP は単独で動くのではなく、必ず下層プロトコル(TCP) の上に成り立つ点を意識してください。

HTTP メッセージの構造

HTTP/1.x のメッセージは テキスト行 で構成されます。リクエストもレスポンスも、おおよそ 「先頭の1行 + 複数のヘッダ行 + 空行 + 本文」 という4ブロックの構造を持ちます。先頭1行だけが種類(リクエスト行 or ステータス行) で異なり、それ以外は共通の作りです。
POINT HTTP/1.x メッセージのフォーマット:
[先頭行(リクエスト行 / ステータス行)] CRLF
[ヘッダ行 1] CRLF
[ヘッダ行 2] CRLF

[空行(CRLF だけ)]
[本文(あれば)]
※ CRLF = \r\n。空行が「ヘッダ終わり・本文開始」の区切りとなります。

リクエストとレスポンスを並べて見る

HTTP リクエスト(クライアント→サーバ)

リクエストは先頭が リクエスト行:メソッド SP URI SP HTTP-バージョン CRLF

GET /docs/index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4) Firefox/124.0
Accept: text/html,application/xhtml+xml
Accept-Language: ja,en;q=0.8
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: session=abc123; theme=dark

(本文なし。GET なので空)

HTTP レスポンス(サーバ→クライアント)

レスポンスは先頭が ステータス行:HTTP-バージョン SP ステータスコード SP 理由句 CRLF

HTTP/1.1 200 OK
Date: Sun, 26 Apr 2026 03:21:08 GMT
Server: nginx/1.24.0
Content-Type: text/html; charset=UTF-8
Content-Length: 1532
Cache-Control: max-age=600
Set-Cookie: session=abc123; Path=/; HttpOnly
Connection: keep-alive

<!DOCTYPE html>
<html>
<head><title>Example</title></head>
<body> … </body>
</html>

並べて比較

リクエスト レスポンス リクエスト行 GET /docs/index.html HTTP/1.1 ヘッダ行(複数) Host: www.example.com User-Agent: Mozilla/5.0 … Accept: text/html, … Cookie: session=abc123 空行(CRLF) 本文 GET の場合は空。POST/PUT で送信データを格納 (例: name=hoge&age=20) ステータス行 HTTP/1.1 200 OK ヘッダ行(複数) Date: Sun, 26 Apr 2026 … Content-Type: text/html Content-Length: 1532 Set-Cookie: session=abc123 空行(CRLF) 本文 HTML / JSON / バイナリ等 長さは Content-Length で示す

図の見方:リクエストとレスポンスは 先頭行が違うだけ で、ヘッダ・空行・本文という構造は共通。空行が必ずヘッダの終わりを示す境界線になっている。

もっと詳しく:CRLF と HTTP の歴史的経緯

HTTP/1.x のメッセージ区切りに CRLF(\r\n) を使うのは、ARPANET 時代から続くインターネットテキストプロトコルの慣習です(SMTP・FTP も同様)。LF(\n) のみではなく CR+LF にしている理由は、Unix・Windows・Mac で改行コードが違っていた時代の互換性確保のため。HTTP/2 以降はテキストではなくバイナリフレームになったため、CRLF の概念は消えています。

主要メソッド:GET / POST / PUT / DELETE / HEAD / OPTIONS

HTTP リクエストの先頭にある メソッド(method) は、サーバに対して 「何をしてほしいのか」 を示す動詞です。HTTP/1.1 で定義された主要メソッドは以下の通り。意味的な性質(冪等性・安全性) も合わせて理解することが重要です。
POINT 用語の整理:
安全(safe) = サーバの状態を変えない(GET / HEAD / OPTIONS)
冪等(idempotent) = 何度実行しても結果が同じ(GET / HEAD / OPTIONS / PUT / DELETE)
非冪等 = 何度実行すると結果が変わりうる(POST)
メソッド意味安全冪等本文
GETリソースを取得する。最も基本原則なし
POSTサーバにデータを送って処理させる(フォーム投稿・新規作成)××あり
PUT指定 URI のリソースを送ったデータで 置き換える(なければ作る)×あり
DELETE指定 URI のリソースを削除する×原則なし
HEADGET と同じだが ヘッダだけ を返す(本文なし)。サイズ確認や生存確認用なし
OPTIONSそのリソースで利用可能なメソッドを問い合わせる(CORS プリフライトでも使用)原則なし
PUT と POST の違い:同じ「データを送る」でも、PUT は 「この URI をこの内容で置き換えて」 という指示なので何度送っても結果は同じ(冪等)。POST は 「処理してほしい」 なので、たとえばコメント投稿なら何度送ると重複コメントが増える(非冪等)。

Q. ブラウザの「リロード」で同じ POST を再送信すると確認ダイアログが出ます。なぜ GET ではダイアログが出ないのに POST だけ出るのでしょう?

考えてみよう: RESTful API の設計では、「GET /users/123 = 取得」「PUT /users/123 = 更新」「DELETE /users/123 = 削除」「POST /users = 新規作成」のようにメソッドと URI を組み合わせて操作を表現します。冪等性を意識して設計することで、ネットワーク障害時の 自動再送 が安全に実装できるという実利があります。

ステータスコードの分類と代表例

レスポンスの 3桁の数値 がステータスコードです。先頭の桁で大分類が決まり、5つのカテゴリに分かれます。HTTP/1.1 (RFC 9110) で標準化されています。
ステータスコードの 5 分類 1xx 情報(Informational) 処理中・継続。例: 100 Continue(続けて本文を送ってよい), 101 Switching Protocols(WebSocket 切替など) 2xx 成功(Success) 正常処理。例: 200 OK, 201 Created(POST/PUT で新規作成成功), 204 No Content(成功したが本文なし) 3xx リダイレクト(Redirection) 移動・条件付き応答。例: 301 Moved Permanently(恒久移動), 302 Found(一時移動), 304 Not Modified(キャッシュ有効) 4xx クライアントエラー(Client Error) 要求側に問題。400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed 5xx サーバエラー(Server Error) サーバ側に問題。500 Internal Server Error, 502 Bad Gateway(プロキシ先障害), 503 Service Unavailable(高負荷・メンテ)

図の見方:ステータスコードは「100の位」だけでもおおよその意味がわかる。2xx なら成功、3xx ならリダイレクト、4xx ならクライアントの責任、5xx ならサーバの責任。エラー対応の最初の手がかりになる。

頻出コードの細かい違い

301 vs 302

どちらも「Location ヘッダで指定された URL に移動して」という指示。
301 Moved Permanently:恒久的な移動。検索エンジンは旧 URL を捨てて新 URL に置き換える。ブラウザもキャッシュして次回から直接新 URL にアクセス。
302 Found:一時的な移動。元の URL は将来また有効になり得る。検索エンジンは旧 URL を維持。

401 vs 403

401 Unauthorized:そもそも 認証していない(誰なのか分からない)。WWW-Authenticate ヘッダで認証方式を提示することが多い。
403 Forbidden:認証は済んだが 権限がない。ログインしているがその管理画面は見られない、というケース。

小問:あるサイトの URL を変更した。新しい URL に永続的に移動したことを検索エンジンに伝えたい。どのステータスコードを返すべき?
正解: B。301 は「恒久的にこっちへ引っ越した」ことを示し、検索エンジンが新 URL でインデックスを書き換えてくれる。302 だと「一時的だから旧 URL も残しておいて」となり、SEO 上の評価が新 URL に移らない。404 は「そのリソースは存在しない」で、移動の意味は伝わらない。

考えてみよう: 304 Not Modified は本文を返さないため通信量を大幅に節約できます。クライアントは If-Modified-SinceIf-None-Match ヘッダで「自分はこの版を持っている」と伝え、サーバは変わっていなければ 304 だけ返します。キャッシュの整合性をヘッダで管理 するのが HTTP の設計の妙です。

主要ヘッダ:必ず押さえたい7つ

HTTP メッセージのヘッダは 「フィールド名: 値」 の形式で、リクエストとレスポンスのメタ情報を運びます。HTTP/1.1 では十数個から数十個のヘッダが付くのが普通。ここでは大学授業で必ず押さえたい主要ヘッダを取り上げます。
ヘッダ名方向役割
Hostreq宛先サイトのホスト名(HTTP/1.1 必須)。仮想ホストの識別に使うHost: www.example.com
User-Agentreqクライアントソフトの識別。ブラウザ名・OS・バージョンなどUser-Agent: Mozilla/5.0 …
Content-Type本文の MIME タイプ。文字コードも含めることが多いContent-Type: text/html; charset=UTF-8
Content-Length本文のバイト数。受信側が「どこまで読めばよいか」を知るためContent-Length: 1532
Cookie / Set-Cookiereq / resサーバがクライアントに小さなテキストを保存させ、次回以降に持参させるCookie: session=abc123
Cache-Controlキャッシュの可否・寿命を指示するディレクティブ群Cache-Control: max-age=3600, public
Authorizationreq認証情報を運ぶ。Basic / Bearer(トークン) など複数方式Authorization: Bearer eyJhbGc…
もっと詳しく:Cache-Control の各ディレクティブ

Cache-Control はカンマ区切りで複数のディレクティブを並べます。代表的なもの:

キャッシュは Web 高速化の主役。CDN、リバースプロキシ、ブラウザ、Service Worker と多段で効くため、ディレクティブの組み合わせを正しく設計することが性能の差になります。

Content-Type で本文の意味が決まる

同じバイト列でも Content-Type: text/html なら HTML として描画され、application/json なら JSON としてパース、application/octet-stream ならダウンロードファイルとして扱われます。ブラウザの「これは何のデータか」の判断は、原則として Content-Type に従います。サーバ側で正しく付与しないと、画像が文字化けして表示される ような事故が起きます。

つながる知識: Content-Type に書く識別子は MIME(Multipurpose Internet Mail Extensions)タイプ と呼ばれ、もとはメールの拡張仕様です(RFC 2045 ほか)。HTTP・メール・WebSocket など複数のプロトコルで共通の語彙として使われている、地味ながら影響範囲の大きい仕様です。

ステートレスである意味と Cookie / セッション

HTTP は設計上 ステートレス(stateless) なプロトコルです。つまりサーバは リクエスト1件ずつを独立して処理 し、HTTP そのものは過去の同じクライアントのリクエストを 覚えていない。一方、実際の Web ではログイン状態が維持されます。これは HTTP が状態を覚えているからではなく、Cookie という仕組みで小さな目印を毎回送り返させ、アプリケーション側で状態を後付けしているからです。
POINT ステートレスの利点 = サーバ側の状態管理が不要で スケールしやすい(複数台のサーバに均等に振っても矛盾しない)。
欠点 = HTTP 単体ではユーザを継続的に識別できない → Cookie + サーバ側セッション で「毎回、同じ人だと分かる」ように補う。

現実とのつながり: 「ログイン状態を維持できない」とは、HTTP だけでは維持できない という意味です。ブラウザはログイン後に受け取った Cookie を保存し、次のリクエストから自動で付けて送ります。サーバはその Cookie のセッション ID を見て、「このリクエストはさっきログインしたユーザから来た」と判断します。つまり、Cookie はステートレスな HTTP の上にログイン状態を無理やり実現するための目印です。

Q. 「HTTP がステートレスだと何が困るのか?」を、具体的なユースケースを2つ以上挙げて答えてみよう。

Cookie の流れ

HTTPは無記憶。Cookieを毎回持参させて同じユーザだと判断する ブラウザ Cookie保存先 Webサーバ セッション表を見る サーバ側セッション表 abc123 → alice def456 → bob 1. 初回ログイン要求 POST /login user=alice&pw=... Cookieなし 2. 認証成功。Cookieがクライアントへ渡される Set-Cookie: session=abc123; HttpOnly クライアント側に保存 ブラウザ内Cookie session=abc123 3. 送るときは、リクエストにCookieも一緒に入る GET /mypage + Cookie: abc123 照合 4. session=abc123 → alice と照合 サーバは「aliceのマイページ」を返す
ステップ1. 最初のログイン要求では、まだログイン用Cookieはありません。HTTPだけを見ると、これはただの1回の POST /login です。
ステップ2. 認証に成功すると、サーバから Set-Cookie ヘッダ付きの応答が返り、クライアント側のブラウザがセッションIDを保存します。同時にサーバ側では abc123 → alice のような対応をセッション表に持ちます。
ステップ3. 2回目以降、ブラウザは対象サイトへのリクエストに保存済みの Cookie を自動で同封します。ユーザが毎回入力しているわけではありません。
ステップ4. サーバはCookieの値をセッション表と照合し、「このリクエストはaliceから来た」と復元します。HTTP自体が記憶しているのではなく、Cookieとアプリ側の表で状態を後付けしています。
1 / 4

図の見方:HTTP 自体はステートレスのまま、Cookie に「セッション ID」という小さな目印を持たせることで、サーバ側のセッションテーブルと突き合わせて状態を復元する。ログイン状態は HTTP が覚えているのではなく、Cookie を毎回持参させることでアプリケーション側が後付けで実現している。

Cookie の主な属性

つながる知識: 「JWT(JSON Web Token) を用いた認証」「OAuth 2.0 のアクセストークン」なども、結局は 「ステートレス HTTP の上で何らかの認証情報を毎回運ぶ」 という発想の延長です。Cookie ベースか Authorization ヘッダベースか、というのは実装の選択。詳細は 第36回 アプリ層プロトコルのセキュア化発展 編で扱います。

パーシステント接続:HTTP/1.0 と HTTP/1.1 の差

Web ページは通常、HTML 1つだけでなく、画像・CSS・JS など 多数のオブジェクト から構成されます。これらをどう運ぶかが HTTP/1.0 と HTTP/1.1 の大きな違いです。

ステップで見る:通信路を毎回作るか、使い回すか

Webページは HTML・CSS・画像などを何回も取りに行く 1ページ = 複数のオブジェクト HTML CSS 画像 JS 部品ごとに HTTP の要求と応答が発生する HTTP/1.0:HTMLを取るたびに作る ブラウザ サーバ HTML 通信路を作る 要求 応答して閉じる CSS また作る 部品ごとに繰り返し HTTP/1.1:通信路を使い回す ブラウザ サーバ 最初に通信路を作る 同じ通信路を開いたまま使う HTML CSS 通信路を作る待ちは最初の1回だけ
ステップ1. Webページは HTML だけではなく、CSS・画像・JavaScript など複数の部品でできている。部品ごとに HTTP の要求と応答が必要になる。
ステップ2. HTTP/1.0 では、HTML を取るために通信路を作り、要求を送り、応答を受け取ったら閉じる。
ステップ3. 次の部品を取るときも、また通信路を作る。オブジェクト数が多いほど、往復確認の待ち時間が積み重なる。
ステップ4. HTTP/1.1 では最初に作った通信路を開いたままにし、次の要求にも使えるようにする。
ステップ5. HTML や CSS を同じ通信路で続けて取りに行けるため、通信路を作る待ち時間は最初の1回だけになる。
1 / 5

図の見方:ボタンで進めると、HTTP/1.0 の「部品ごとに通信路を作る」流れと、HTTP/1.1 の「1本の通信路を使い回す」流れを順番に比較できる。

HTTP/1.0:ノンパーシステント

HTTP/1.0 は 1リクエスト=1 TCP コネクション が基本です。ここでいう TCP コネクションとは、HTTP のリクエストを流す前にブラウザとサーバの間で作る 通信路 のことです。通信路を作るたびに「送ってよい?」「よい」「では送る」のような往復確認(後で学ぶ 3-way ハンドシェイク)が必要になるため、オブジェクトごとに 1往復ぶんの待ち時間 が積み重なります。この往復時間を RTT と呼びます。

オブジェクトが 50 個あれば、通信路を作る確認だけで 50 回ぶん発生します。仮に1往復が 50 ms なら、それだけで 2.5 秒の待ち時間になります。

HTTP/1.1:パーシステント + パイプライン

HTTP/1.1 は パーシステント(継続型)接続標準で有効 にしました。1本の TCP コネクションで複数のリクエスト・レスポンスを連続して送れます。Connection: keep-alive ヘッダ(または HTTP/1.1 のデフォルト動作) でこの挙動を表します。

ただしパイプラインには弱点があります:応答は 送った順番 で返ってこないと困るため、サーバは順序を守って返す必要があり、先頭のリクエスト処理が遅いと後続の応答も詰まる(後述の HOL ブロッキング)。実際にはブラウザはパイプラインを 無効化 していることが多く、代わりに 1サイトあたり6本前後の TCP コネクションを並列に張る という回避策を取っていました。

HTTP/2:多重化

HTTP/2 は別のアプローチで根本解決します:1本の TCP コネクションの中で論理的な「ストリーム」を複数同時に流す(多重化)。次のセクションで詳述します。

考えてみよう: HTTP/1.0 → 1.1 の進化は、「通信路の使い回し」によって往復確認の回数を減らす工夫でした。ネットワークでは、どれだけ高速な回線でも相手との距離に応じた往復待ち時間が残ります。そのため 「往復回数を減らす」 はネットワーク高速化の重要な考え方です。HTTP/2・HTTP/3 もこの哲学の延長線上にあります。

HTTP/2 の改善点

HTTP/2(RFC 9113、当初 RFC 7540) は セマンティクス(メソッド・ステータス・ヘッダの意味) は HTTP/1.1 と同じ まま、下層のフレーミングと多重化を全面的に作り変えた 版です。Google の SPDY を出発点に IETF で標準化されました。
POINT HTTP/2 の4つの柱:
バイナリフレーミング(テキスト → バイナリ)
ストリームの多重化(1 TCP に複数論理ストリーム)
ヘッダ圧縮(HPACK)(冗長ヘッダの圧縮)
サーバプッシュ(クライアントが要求する前にサーバから関連リソースを送る)

① バイナリフレーミング

HTTP/1.x のテキストパーサは「行末を探す」「空行を探す」といった処理が複雑でした。HTTP/2 は 固定長ヘッダ + ペイロードフレーム 単位に再設計し、パーサがシンプル・高速になりました。フレームの種類は HEADERS / DATA / SETTINGS / PING / GOAWAY / WINDOW_UPDATE などがあります。

② ストリームの多重化(multiplexing)

1 本の TCP コネクションの中に 論理的な「ストリーム」 を複数走らせ、それぞれを並行して進めます。各ストリームには ID が付き、フレームには「どのストリームに属するか」が書かれているので、受信側が再組立てできます。

HTTP/1.1(直列):1本につき1リクエストずつ HTTP/2(多重化):1本に複数ストリーム並行 TCP コネクション × 1 HTML img1 img2 CSS 1つ終わってから次。先頭が遅いと全体が遅い → ブラウザは TCP を6本並列で張って回避 TCP コネクション × 1(その中に複数ストリーム) stream 1 (HTML) stream 3 (CSS) stream 5 (img1) stream 7 (img2) フレーム単位で細切れに混ぜて送る

図の見方:色は同じオブジェクトを表す。HTML は緑、img1 は黄、img2 は紫、CSS は青。左の HTTP/1.1 はオブジェクトを1つずつ直列で送るため、先頭のオブジェクトの応答完了を待たないと次が始められない。右の HTTP/2 は1つの TCP の中で複数のストリームのフレームを 細切れに混ぜて送る ため、全リクエストがほぼ同時並行で進む。

③ ヘッダ圧縮 ─ HPACK

HTTP/1.x では、毎リクエストごとに同じような User-Agent / Accept / Cookie を平文で繰り返し送っていました。これは特に多数の小さなリクエストでは無視できないオーバーヘッドです。HTTP/2 は HPACK(RFC 7541) という専用の圧縮アルゴリズムを導入しました。

もっと詳しく:HPACK の概要

結果として、HTTP/2 のヘッダは数バイト〜数十バイトに収まることが多く、ネットワーク負荷とレイテンシが大きく減少します。

なお、HPACK は 状態を持つ(動的テーブル) ためにヘッダを順序通り処理する必要があり、これが HOL ブロッキングの一因にもなります。HTTP/3 では順不同でも安全な QPACK(RFC 9204) に置き換えられています。

④ サーバプッシュ(server push)

サーバが「どうせクライアントは次にこれを要求するだろう」と予測して、要求を待たずに関連リソースを 先回りで送る 機能です。たとえば HTML の応答と一緒に、その HTML が参照する CSS や画像をプッシュしておけば、クライアントが <link rel="stylesheet"> を解析してから改めて要求する RTT を節約できます。

実運用では キャッシュされていることに気づかずに重複送信してしまう 等の問題があり、結局あまり活用されませんでした。Chrome は 2022 年にサーバプッシュのサポートを廃止しています。代替として 103 Early Hints(早期ヒント) でリンク情報を先に伝える方式が普及しつつあります。

HOL ブロッキング問題と HTTP/3 への動機

HTTP/2 でアプリ層の HOL は解決しましたが、下層 TCP の HOL ブロッキング という新たな限界が見えてきました。これが HTTP/3 / QUIC の設計動機です。
POINT HOL(Head-of-Line) ブロッキング:列の先頭が詰まると、後ろが順番待ちで全部止まる現象。
HTTP/1.1 パイプライン → アプリ層 HOL(順序保証のため先頭が遅いと後続も止まる)
HTTP/2 → アプリ層 HOL は解消。だが TCP の順序保証 によって 1パケットでも欠落すると、別のストリームの後続パケットまで配送が止まる(TCP 層 HOL)

図で見る:TCP 層 HOL と QUIC の違い

1つの欠落が、どこまで足止めするかが違う HTTP/2 over TCP:1本の順番待ち 複数ストリームを1本の TCP の順序に並べる HTML CSS 欠落 img2 CSS HTML ここが届かない 後ろは届いていてもアプリへ渡せない TCP は順番通りに渡す 欠けた番号が再送されるまで全体が止まる HTTP/3 over QUIC:ストリームごとに独立 欠けたストリームだけが再送待ちになる HTML OK OK CSS OK OK img1 OK 欠落 img2 OK OK 他のストリームは先にアプリへ渡せる

図の見方:HTTP/2 はストリームを多重化しても、下層の TCP は1本の順序付きの列として扱う。そのため途中のパケットが1つ欠けると、後ろにある別ストリームのデータもアプリへ渡せず待たされる。QUIC はストリームごとに順序保証を分けるため、欠けたストリームだけが待ち、他のストリームは進められる。

なぜ TCP 層で HOL が起きるのか

TCP は受信したセグメントを 必ず順序通りにアプリへ渡す 仕様です。HTTP/2 のように1本の TCP に複数の論理ストリームを乗せると、たとえ ストリーム3 のパケットだけ落ちて、ストリーム5 や 7 のパケットが先に届いていても、TCP は「3 が来るまで全部保留」してしまいます。アプリ層では並行に進められるはずなのに、トランスポート層が足を引っ張る形です。

HTTP/3 = QUIC + HTTP の新しい組み合わせ

QUIC は Google が開発し IETF で標準化された UDP の上で動く新しいトランスポート です。TCP の「コネクション」「再送」「輻輳制御」「TLS による暗号化」を UDP の上で1つにまとめて 実装し、ストリームごとに独立した順序保証を持ちます。これにより TCP 層 HOL が解消されます。HTTP/3 は QUIC の上で HTTP のセマンティクスを動かすマッピングです。

QUIC は OS カーネルではなく ユーザ空間で実装される ため、進化が速いという別の利点もあります。ただし通信路の機器が UDP を絞っている環境では使えないなど、現場での課題も残ります。詳細は 発展編 QUIC/HTTP3 で扱います。

まとめと用語チェック

SUMMARY 1. HTTP は要求応答型・テキスト(HTTP/1.x) ベースのアプリ層プロトコル。下層は通常 TCP(80) または TLS+TCP(443)
2. メッセージは 先頭行 + ヘッダ行 + 空行 + 本文 の4ブロック構造
3. 主要メソッドは GET / POST / PUT / DELETE / HEAD / OPTIONS。安全性・冪等性で性質が分かれる
4. ステータスコードは 1xx〜5xx の5分類。よく出る 200/301/302/304/400/401/403/404/500/502/503 は意味を覚える
5. 主要ヘッダ:Host・User-Agent・Content-Type・Content-Length・Cookie・Cache-Control・Authorization
6. HTTP はステートレス。継続的な状態は Cookie + サーバ側セッション で実現
7. HTTP/1.0 → 1.1:パーシステント接続(keep-alive) で TCP を再利用。パイプラインは HOL のため実用化されず
8. HTTP/2:バイナリフレーム、ストリーム多重化、HPACK ヘッダ圧縮、サーバプッシュ。アプリ層 HOL を解消
9. ただし TCP 層 HOL が残るため、HTTP/3 = QUIC(UDP 上) で根本対処

用語チェック

用語1行説明
リクエスト行 / ステータス行HTTP メッセージの先頭1行。メソッド+URI+版 / 版+コード+理由句
メソッドサーバへの動詞指示。GET / POST / PUT / DELETE / HEAD / OPTIONS など
安全 / 冪等サーバ状態を変えない / 何度実行しても結果が同じ。メソッド設計の指針
ステータスコードレスポンスの3桁数値。1xx 情報・2xx 成功・3xx リダイレクト・4xx クライアント・5xx サーバ
ヘッダ「フィールド名: 値」の形式でメッセージのメタ情報を運ぶ
Host ヘッダHTTP/1.1 必須。同一 IP の仮想ホストを識別
Content-Type / Length本文の MIME タイプと長さ
Cookie / Set-Cookieサーバが状態管理用に小さなテキストを保存させ、毎回送り返させる仕組み
Cache-Controlキャッシュ可否・寿命のディレクティブ群(max-age / no-cache / no-store 等)
Authorization認証情報を運ぶヘッダ。Basic / Bearer 等
ステートレスサーバが過去のリクエストを覚えていない設計性質
パーシステント接続1 本の TCP で複数 HTTP リクエストを使い回す(HTTP/1.1 デフォルト)
パイプライン応答を待たずに連続でリクエストを送る。HOL のため実用化されず
バイナリフレーミングHTTP/2 のメッセージ表現。テキスト行ではなくフレーム
ストリーム多重化1 TCP の中で複数論理ストリームを並行に流す HTTP/2 の機構
HPACKHTTP/2 のヘッダ圧縮(RFC 7541)。静的+動的テーブル+ハフマン
サーバプッシュクライアント要求前にサーバが関連リソースを送る機能(HTTP/2)
HOL ブロッキング列の先頭が詰まると後続も止まる現象。アプリ層・TCP 層の両方で起きうる
QUIC / HTTP/3UDP 上に再設計された次世代トランスポートと、その上の HTTP
NEXT: 次回(第13回)は本講で学んだ HTTP を 自分で書いて動かすHTTP プログラミング」のハンズオン。telnet で生 HTTP を打つところから、curl・Python・Node で簡単なクライアント/サーバを実装します。

確認問題

問1. HTTP/1.1 のリクエストメッセージの構造として最も正しいものを1つ選べ。

次の選択肢から最も適切なものを選択してください。
A. メソッド行 + 本文 + ヘッダ行 + 空行
B. ステータス行 + ヘッダ行 + 空行 + 本文
C. リクエスト行 + ヘッダ行(複数) + 空行 + 本文
D. ヘッダ行 + メソッド行 + 本文(空行は不要)
正解:C
HTTP/1.x のリクエストは「リクエスト行(METHOD URI VERSION) + 0個以上のヘッダ行 + 空行(ヘッダの終端) + 本文」。空行はヘッダと本文の境界を示す重要な区切り。B はレスポンスの構造(ステータス行で始まる)、A・D は順序が誤り。

問2. HTTP メソッドの性質について正しい記述を選べ。

次の選択肢から最も適切なものを選択してください。
A. POST は冪等であり、何度送っても結果は同じになる
B. PUT は冪等で、同じ URI に同じ本文を何度 PUT しても結果は同じ
C. GET は安全ではない(サーバ状態を変える)
D. HEAD は POST と同じ意味を持ち、本文を送るためのメソッドである
正解:B
PUT は「指定 URI をこの内容で置き換えよ」なので、同じ要求を何度送っても最終状態は同一(冪等)。A は誤り(POST は非冪等で、二重投稿が起きうる)。C も誤り(GET は安全=サーバ状態を変えない)。D は誤り(HEAD は GET と同等で本文を返さない)。

問3. 301 と 302 の違いとして最も正しいのはどれか。

次の選択肢から最も適切なものを選択してください。
A. 301 は認証が必要で、302 は認証が不要
B. 301 はキャッシュ用で、302 はリダイレクトには使われない
C. 301 は恒久的な移動、302 は一時的な移動を意味する
D. 301 はサーバエラー、302 はクライアントエラーである
正解:C
301 Moved Permanently は「恒久移動」、302 Found は「一時移動」。検索エンジンは 301 を見ると新 URL でインデックスを更新するが、302 だと旧 URL のままにする。A は無関係(認証は 401)、B も誤り(304 がキャッシュ関連)、D も誤り(3xx はリダイレクトで、サーバ/クライアントエラーは 5xx/4xx)。

問4. HTTP がステートレスであることに関する説明として最も適切なものを選べ。

次の選択肢から最も適切なものを選択してください。
A. ステートレスとは通信経路で暗号化されないことを意味する
B. ステートレスでは Cookie をサーバが保存できないため、ログインは不可能である
C. ステートレスとは TCP コネクションを使わずに UDP で通信することである
D. ステートレスとはサーバが過去のリクエストを記憶しない設計で、Cookie 等で状態を補う
正解:D
HTTP は本来「リクエスト1件ずつを独立に処理し、過去を覚えない」設計。これによりスケーラビリティが高い反面、ログインのような継続状態が表現できないので、Set-Cookie / Cookie ヘッダで小さな目印をクライアントに持たせ、サーバ側のセッションテーブルと突き合わせて状態を復元する。A(暗号化と無関係)、B(Cookie + セッションでログインは可能)、C(トランスポートとは別の話) はすべて誤り。

問5. HTTP/2 の改善点として誤っているものはどれか。

次の選択肢から最も適切なものを選択してください。
A. メッセージをテキスト行ではなくバイナリフレームで表現する
B. UDP の上で動作することにより TCP の HOL ブロッキングを完全に解消する
C. 1 本の TCP コネクションの中で複数のストリームを多重化する
D. HPACK によりリクエスト/レスポンスのヘッダを圧縮する
正解:B
HTTP/2 は依然として TCP の上 で動くため、TCP の順序保証に起因する HOL ブロッキングは残る。これを根本解決したのは HTTP/3 = QUIC(UDP の上に再設計された新トランスポート)。A・C・D は HTTP/2 の正しい改善点(バイナリフレーミング・ストリーム多重化・HPACK ヘッダ圧縮)。
← PREV
第11回 階層化とカプセル化
NEXT →
第13回 DNS の階層と解決手順