用語辞典・通信プロトコル

WebSocket

WebSocketとは

WebSocketは、一つの接続を保ったまま、ブラウザとサーバーが双方向にデータを送受信する仕組みです。プロトコル名はWebSocket Protocol(ウェブソケット・プロトコル)で、ウェブソケットと読みます。

最初にHTTPを利用したopeningハンドシェイクで、サーバーがWebSocketを受け入れるか確認します。成立後はHTTP要求をメッセージごとに繰り返さず、同じ接続上でクライアント・サーバーのどちらからでもWebSocketフレームを送れます。

「双方向」は、要求へ応答する順番に限られず、接続中ならサーバーから新着通知を自発的に送れる全二重通信を意味します。ただし切断後の再接続、メッセージ再送、保存はアプリ側の設計です。

HTTPの開始確認後、同じ保護接続を双方向メッセージの通路として使い続けるメッセージ断片の間にも制御フレームを処理し、ping・pong、close、送信待ちを管理する
ブラウザーとサーバーがHTTP開始ハンドシェイクの鍵値を確認後、一つのTLS保護接続を全二重のWebSocket通路へ切り替え、メッセージの断片化と再構成、途中の制御フレーム、クライアントマスク、pingとpong、双方close、送信キューの増加を示した図解
図1マスクはクライアントからサーバーへのフレームを変換する規則で、暗号化ではありません。WSSでは別にTLSが通信を保護します。

開始時だけHTTPを使い、その後はWebSocketフレームを交換する

開始、データ交換、維持確認、正常終了を一つの接続状態として扱うHTTP版により開始方法が違っても、成立後のWebSocketメッセージ意味は共通する
Open接続候補を要求

URL、Origin、対応版、ランダム鍵、任意のサブプロトコル・拡張を提示する

Acceptサーバーが受諾

鍵から導く応答値と、選択したサブプロトコル・拡張を返す

Messageテキスト・バイナリー

一つのアプリメッセージを一つ以上のデータフレームとして送る

Controlping・pong・close

小さな制御フレームを断片化せず、データ断片の間にも処理する

Maskクライアント側変換

ブラウザーからサーバーへの各フレームを予測不能なマスキング鍵で変換する

Close双方で終了確認

終了コードと短い理由を送り合い、基盤接続を閉じて再接続判断へ進む

図2subprotocolはWebSocket上のアプリ規則です。クライアントが提示し、サーバーが選んだ値を双方が同じ意味で実装します。

HTTP/1.1ではUpgrade、HTTP/2・3ではExtended CONNECTを使う

HTTP/1.1ではGET要求にUpgradeとConnection、Sec-WebSocket-Key、Versionなどを入れ、サーバーが101 Switching Protocolsと鍵に対応するAccept値を返します。これにより、意図しない通常HTTP応答をWebSocketとして扱うことを防ぎます。

HTTP/2ではConnection・Upgradeを使えないため、RFC 8441のExtended CONNECTでWebSocketを開始します。HTTP/3でも対応するExtended CONNECT方式があります。開発者ツールでHTTP版を確認するとき、開始ハンドシェイクの形式と成立後のWebSocketデータを分けて読む必要があります。

メッセージ境界を保ち、必要なら複数フレームへ断片化する

WebSocketはUTF-8のテキストメッセージと任意バイトのバイナリーメッセージを提供します。一つのメッセージを最初のデータフレームとcontinuationフレームへ分け、最後のFINで完結を示せます。受信側は断片を順番に再構成して一つのメッセージとしてアプリへ渡します。

TCP上の一回の受信とWebSocketフレーム、WebSocketメッセージはそれぞれ別境界です。大きなメッセージを無制限に受けるとメモリーを消費するため、許容サイズ、断片処理、形式検証をサーバー・クライアント双方に設けます。

ping・pongは接続維持の手掛かりで、アプリ処理完了の確認ではない

ping制御フレームを受けた側は対応するpongを返します。途中のNAT・プロキシで接続状態が消えるのを防ぐkeepaliveや、相手プロセスがフレームを処理できるかの確認に使えます。

pongが返っても、チャット保存、注文処理、通知反映などアプリの処理成功は分かりません。重要メッセージにはアプリ固有IDと受領応答を用意します。切断時にどこまで処理されたか曖昧なら、再接続後に状態を照会して冪等に再送します。

WSSはTLSで保護し、Originと利用者認証も検証する

wss(WebSocket Secure/ウェブソケット・セキュア)TLSでWebSocket接続を保護し、証明書の名前を検証します。wsは平文です。HTTPSページからは通常WSSを使い、混在コンテンツを避けます。

ブラウザーはハンドシェイクへOriginを送りますが、通常のWebSocket APIでは同一生成元だけに自動制限されません。サーバーが許可Originを検証し、Cookieだけに依存するサイト横断WebSocket hijackingを防ぎます。利用者認証、認可、有効期限、ログアウト時切断もアプリで管理します。

マスキングはプロキシ保護のフレーム規則で、秘密を隠す暗号ではない

ブラウザークライアントからサーバーへ送るフレームは毎回新しいマスキング鍵でペイロードをXOR変換します。ネットワーク上の攻撃者から内容を隠す強度はなく、サーバーからクライアント方向はマスクしません。

目的は、悪意あるスクリプトが見かけ上のHTTP文字列を生成し、古い中継キャッシュなどを誤動作させる攻撃を難しくすることです。機密性・完全性・相手認証にはWSSのTLSを使います。

送信速度と受信処理速度が合わない場合、キュー上限を決める

ネットワークが遅いのにアプリがsendを続けると、送信バッファーが増えます。ブラウザーのbufferedAmountを監視し、重要度の低い更新をまとめる、送信を待つ、接続を閉じるなどの方針を決めます。

受信側も画面描画やデータベース処理より速く届けば詰まります。WebSocketはメッセージを永続保存・再配信するメッセージキューではないため、再接続、順序番号、再送、オフライン受信が必要ならサーバー側の履歴とアプリプロトコルを追加します。

仕様の確認資料:RFC 6455「The WebSocket Protocol」RFC 8441「Bootstrapping WebSockets with HTTP/2」RFC 9220「Bootstrapping WebSockets with HTTP/3」

関連用語