はじめに
こんにちは!アメリカで独学でソフトウェアエンジニアを目指しているものです。
現在、RubyとRuby on Railsの勉強をする合間に、Webの基礎的な仕組みを学んでいます。
本記事では、Web通信の根幹となるHTTPについて、その基本的な流れを初心者向けに説明していきます。
ここでは主に「HTTP/1.1」を前提とした典型的な手順をまとめています。近年はHTTP/2やHTTP/3といった新しいバージョンが利用されるケースも多いですが、本記事では基本のイメージをつかむことを目的としています。
HTTP通信の全体の流れ
HTTP通信は大きく5つのステップで構成されます
- TCP接続の確立(3ウェイハンドシェイク)
- (HTTPSの場合)SSL/TLSハンドシェイク
- HTTPリクエストとHTTPヘッダーの送信
- HTTPレスポンスとHTTPヘッダーの受信
- 必要に応じてTCPコネクションの終了(4ウェイハンドシェイク)
なお、実際のWebブラウザは1つのTCPコネクションを複数のリクエスト・レスポンスのやり取りに使い続ける(Keep-Alive)ため、毎回この5ステップが1セットで完結するとは限りません。
以下では、基本的な一連の流れを示します。
1.TCP接続の確立(3ウェイハンドシェイク)
HTTP通信を始めるには、まずクライアント(ブラウザなど)とサーバー間でTCP接続を確立する必要があります。TCPは信頼性の高い通信を行うためのプロトコルで、以下の「3ウェイハンドシェイク」と呼ばれる手順で接続が成立します。
3ウェイハンドシェイクの手順
- クライアント → サーバー:SYN(接続要求)
- サーバー → クライアント:SYN + ACK(要求受諾と応答確認)
- クライアント → サーバー:ACK(応答確認完了)
これでTCPによる通信路が確保され、HTTPメッセージをやり取りする準備が整います。
2.(HTTPSの場合)SSL/TLSハンドシェイク
現在、多くのWebサイトはHTTPS(HTTP + TLS)を採用しています。これは通信内容を暗号化してセキュリティを高めるためです。
例えば、オンラインショッピングでクレジットカード番号や個人情報を送信する際、HTTPSであれば第三者による盗聴や改ざんが困難になります。
HTTPSを利用する場合、TCP接続確立後にSSL/TLSハンドシェイクを行います。このハンドシェイクによって、クライアントとサーバーは共通の暗号鍵を生成し、以降のHTTP通信は暗号化されて行われます。
SSL/TLSハンドシェイクの手順(TLS 1.2を例にしたイメージ)
- クライアントハロー:クライアントが使用可能な暗号スイート(通信暗号方式)をサーバーに提示
- サーバーハロー:サーバーが暗号方式を選択し、サーバー証明書をクライアントに送信
- 証明書検証・鍵交換:クライアントはサーバー証明書を検証し、鍵交換方式(一般的にはDiffie-Hellmanなど)を用いて共通鍵を確立
- 暗号化開始:以後の通信は共通鍵による暗号化通信が行われる
(注:TLS 1.3ではハンドシェイクがよりシンプルになっています。)
3.HTTPリクエストとHTTPヘッダーの送信
TCP接続(およびHTTPSならTLSハンドシェイク)完了後、クライアントはサーバーにHTTPリクエストを送信します。
HTTPリクエストの構造
-
リクエストライン:
例GET /index.html HTTP/1.1
ここにはHTTPメソッド(GET、POSTなど)、リクエスト先のパス、HTTPバージョンが含まれます。 -
リクエストヘッダー:
例
Host: www.example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html
Cookie: ...
ブラウザの種類、要求するデータ形式、セッション情報などが記載されます。 -
リクエストボディ:
GETリクエストでは通常空ですが、POSTリクエストなどではフォームデータやファイルがここに含まれます。
4. HTTPレスポンスとHTTPヘッダーの受信
サーバーはリクエストを処理し、結果をHTTPレスポンスとして返します。
HTTPレスポンスの構造
-
ステータスライン:
例HTTP/1.1 200 OK
HTTPバージョンとステータスコード(200は成功、404はファイルが見つからないなど)が記載されます。 -
レスポンスヘッダー:
例
Content-Type: text/html; charset=UTF-8
Content-Length: 12345
Cache-Control: no-cache
コンテンツの種類、エンコーディング、キャッシュポリシーなどが含まれます。 -
レスポンスボディ:
HTML、CSS、JavaScript、画像、JSONなど、実際にクライアントが表示・処理するデータがここに含まれます。
ブラウザは受け取ったレスポンスを解析・表示し、ユーザーが目にするWebページが画面に描画されます。
5.必要に応じたTCPコネクションの終了(4ウェイハンドシェイク)
通信が完了し、もはやそのTCP接続を使わない場合は、4ウェイハンドシェイクと呼ばれる手続きでコネクションを終了します。
4ウェイハンドシェイクの手順
- クライアント → サーバー:FIN(終了要求)
- サーバー → クライアント:ACK(要求受理)
- サーバー → クライアント:FIN(サーバーも終了要求)
- クライアント → サーバー:ACK(サーバー側の終了要求確認)
これでTCP接続が完全に切断されます。
ただし、HTTP/1.1では「Keep-Alive」により、1つのTCPコネクションで複数のHTTPリクエスト・レスポンスを処理することが多いため、ページ内の複数リソース(画像、スクリプト、CSSなど)を取得する間はコネクションを維持し、その後まとめて切断することが一般的です。
HTTP/2やHTTP/3では?
本記事ではHTTP/1.1を前提とした基本的な流れを説明しました。しかし、近年はHTTP/2やHTTP/3が普及しています。
- HTTP/2: 一度確立したコネクション上でストリーム(仮想的な複数の通信路)を並行的に扱うことで効率化
- HTTP/3: TCPではなくUDPをベース(QUICプロトコル)として、さらに接続確立を高速化
まとめ
本日はHTTP通信の全体の流れについてまとめてみました
- TCP接続確立(3ウェイハンドシェイク)
- HTTPSならSSL/TLSハンドシェイクで暗号化開始
- クライアントからHTTPリクエスト・ヘッダー送信
- サーバーからHTTPレスポンス・ヘッダー受信
- 必要に応じてTCPコネクションを終了(4ウェイハンドシェイク)
今後もWeb技術について学び、整理できたらまた別の記事で共有していこうと思います。
ぜひ、気になる方はChromeデベロッパーツールやブラウザ拡張機能を使い、実際のHTTPリクエスト・レスポンスを観察してみてください!