HTTPハンドシェイクから始まる永続的な全二重通信プロトコル。Slackやオンラインゲームに使われています。
WebSocket は、1回の HTTP ハンドシェイクで接続を確立した後、その接続を使い続けて双方向にメッセージを交換できるプロトコルです(RFC 6455)。
通常の HTTP では、クライアントがリクエストを送り、サーバーがレスポンスを返す、という1往復ごとに完結する通信です。サーバーからクライアントに「新しいデータがあるよ」と自発的に通知することはできません。
WebSocket は接続を繋ぎっぱなしにして、いつでも両側からデータを送れる仕組みです。チャットアプリで相手のメッセージがリアルタイムに表示されたり、株価がリアルタイムに更新されたりするのは WebSocket のおかげです。
HTTP でリアルタイム通信をしようとすると、クライアントが「何か新しいデータありますか?」と定期的にサーバーに問い合わせるポーリングが必要です。しかしこれには問題があります。
WebSocket はこれらの問題をすべて解決します。接続を1回確立すれば、データが発生した瞬間にサーバーからプッシュでき、ヘッダーオーバーヘッドも最小(2バイト〜)です。
Upgrade: websocket ヘッダーで「WebSocket に切り替えたい」とリクエスト101 Switching Protocols で承認。以降は HTTP ではなく WebSocket プロトコルで通信Host・Cookie・User-Agent などのヘッダーが毎回数百バイト付きます。株価アプリのように1秒間に何十回もデータを更新する場合、この差は通信量と遅延に大きく影響します。Upgrade: websocket と Connection: Upgrade を含むHTTP GETリクエストを送ります。サーバーが 101 Switching Protocols で応答した瞬間、HTTPの通信は終わりWebSocketプロトコルへ切り替わります。この切り替えは1回だけ行われ、以後は同じTCP接続を使い続けます。Content-Type や Cookie などの数百バイトのヘッダーを付け直す必要がなく、オーバーヘッドが極めて小さいのが特徴です。上のツールのステップ4・5で「Text Frame」として表示されているのがこのフレームです。opcode: 0x1 や opcode: 0x8 として表示されます。WebSocket では HTTP のリクエスト/レスポンスの代わりにフレームという単位でデータをやり取りします。フレームのヘッダーは最小2バイトで、HTTP ヘッダー(数百バイト)と比べて非常に軽量です。
HTTP では毎回 Host, Cookie, User-Agent などのヘッダーが付きますが、WebSocket フレームにはそれらが一切ありません。1秒間に何十回もデータを送る用途(株価、ゲーム等)では、この差が通信量とレイテンシに大きく影響します。
FIN(1ビット): このフレームがメッセージの最後かどうか。大きなデータは複数フレームに分割(フラグメンテーション)されます。
opcode(4ビット): フレームの種類を示します。
MASK(1ビット): クライアント → サーバーの通信では必ず 1(マスクあり)。サーバー → クライアントは 0(マスクなし)。これはプロキシの誤動作を防ぐためのルールです(RFC 6455)。payload length(7ビット): ペイロードのバイト数。125以下なら7ビットに直接格納、126以上なら後続の2バイトまたは8バイトで拡張します。
クライアントからサーバーに送るフレームにだけ付くランダムな4バイトです。ペイロードの各バイトと XOR して「マスク」します。暗号化ではなく、キャッシュポイズニング攻撃を防ぐための仕組みです。サーバー側で同じキーで XOR すれば元に戻ります。
Upgrade: websocket ヘッダーを含むHTTP GETリクエストを送信します。Sec-WebSocket-Accept キーを含む101レスポンスを返し、プロトコル切り替えを承認します。| 比較項目 | HTTP | WebSocket |
|---|---|---|
| 通信方向 | 単方向(リクエスト→レスポンス) | 双方向(全二重) |
| 接続の持続 | リクエストごとに接続/切断 | 1回接続して使い続ける |
| サーバープッシュ | 不可(SSEは一方向のみ) | 可能(いつでも送信) |
| ヘッダーサイズ | 数百バイト〜数KB | 2〜14バイト(最小) |
| リアルタイム性 | ポーリングが必要 | 即時(低レイテンシ) |
| 用途 | REST API・Webページ | チャット・ゲーム・通知 |