RFC 6455 - The WebSocket Protocol (WebSocketプロトコル)
- ステータス: Proposed Standard
- 発行日: December 2011
- ストリーム: IETF
- エラッタ: エラッタなし
概要 (Abstract)
WebSocketプロトコル (WebSocket Protocol) は、単一のTCP接続上でクライアントとサーバー間の全二重通信 (Full-Duplex Communication) を実現します。WebSocketプロトコルは、Webブラウザおよびwebサーバーに実装されることを想定していますが、任意のクライアントまたはサーバーアプリケーションで使用できます。
WebSocketプロトコルは、TCPベースの独立したプロトコルです。HTTPとの唯一の関係は、そのハンドシェイク (Handshake) がHTTPサーバーによってアップグレードリクエスト (Upgrade Request) として解釈されることです。
目次 (Table of Contents)
- 1. Introduction (はじめに)
- 1.1 Background (背景)
- 1.2 Protocol Overview (プロトコル概要)
- 1.3 Opening Handshake (オープニングハンドシェイク)
- 1.4 Closing Handshake (クロージングハンドシェイク)
- 1.5 Design Philosophy (設計思想)
- 1.6 Security Model (セキュリティモデル)
- 1.7 Relationship to TCP and HTTP (TCPおよびHTTPとの関係)
- 1.8 Establishing a Connection (接続の確立)
- 1.9 Subprotocols and Extensions (サブプロトコルと拡張)
- 2. Conformance Requirements (適合性要件)
- 2.1 Terminology and Other Conventions (用語とその他の規約)
- 3. WebSocket URIs
- 4. Opening Handshake (オープニングハンドシェイク)
- 4.1 Client Requirements (クライアント要件)
- 4.2 Server-Side Requirements (サーバー側要件)
- 4.3 Collecting Extensions and Subprotocols (拡張とサブプロトコルの収集)
- 4.4 Supporting Multiple Versions (複数バージョンのサポート)
- 5. Data Framing (データフレーミング)
- 5.1 Overview (概要)
- 5.2 Base Framing Protocol (基本フレーミングプロトコル)
- 5.3 Client-to-Server Masking (クライアントからサーバーへのマスキング)
- 5.4 Fragmentation (フラグメンテーション)
- 5.5 Control Frames (制御フレーム)
- 5.6 Data Frames (データフレーム)
- 5.7 Examples (例)
- 5.8 Extensibility (拡張性)
- 6. Sending and Receiving Data (データの送受信)
- 6.1 Sending Data (データの送信)
- 6.2 Receiving Data (データの受信)
- 7. Closing the Connection (接続のクローズ)
- 7.1 Definitions (定義)
- 7.2 Abnormal Closures (異常クローズ)
- 7.3 Normal Closure (正常クローズ)
- 7.4 Status Codes (ステータスコード)
- 8. Error Handling (エラー処理)
- 8.1 Handling Errors in UTF-8-Encoded Data (UTF-8エンコードデータのエラー処理)
- 9. Extensions (拡張)
- 9.1 Negotiating Extensions (拡張のネゴシエーション)
- 9.2 Known Extensions (既知の拡張)
- 10. Security Considerations (セキュリティに関する考慮事項)
- 10.1 Non-Browser Clients (非ブラウザクライアント)
- 10.2 Origin Considerations (オリジンに関する考慮事項)
- 10.3 Attacks On Infrastructure (インフラストラクチャへの攻撃)
- 10.4 Implementation-Specific Limits (実装固有の制限)
- 10.5 WebSocket Client Authentication (WebSocketクライアント認証)
- 10.6 Connection Confidentiality and Integrity (接続の機密性と完全性)
- 10.7 Handling of Invalid Data (無効なデータの処理)
- 10.8 Use of SHA-1 (SHA-1の使用)
- 11. IANA Considerations (IANAに関する考慮事項)
- 12. Using WebSocket Protocol from Other Specifications (他の仕様からのWebSocketプロトコルの使用)
- 13. Acknowledgements (謝辞)
- 14. References (参考文献)
- 14.1 Normative References (規範的参考文献)
- 14.2 Informative References (参考情報)
追加リソース
- 📖 実装ガイド: WebSocketプロトコル実装ガイド - 詳細な技術説明、コード例、ベストプラクティス
- 🔗 公式RFC: RFC 6455
- 📋 DataTracker: RFC 6455 DataTracker
- 🐛 正誤表: RFC Editor Errata
関連RFC
- RFC 6455: The WebSocket Protocol ← 本文書
- RFC 7692: WebSocket Compression Extensions (WebSocket圧縮拡張)
- RFC 8441: Bootstrapping WebSockets with HTTP/2 (HTTP/2でのWebSocketブートストラップ)
クイックリファレンス
WebSocket URI形式
ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
ws://- 暗号化されていない接続 (デフォルトポート80)wss://- TLS暗号化接続 (デフォルトポート443、本番環境推奨)
ハンドシェイク例
クライアントリクエスト:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: http://example.com
サーバーレスポンス:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
フレームタイプ (Opcode)
| Opcode | タイプ | 説明 |
|---|---|---|
| 0x0 | Continuation | 継続フレーム |
| 0x1 | Text | テキストフレーム (UTF-8) |
| 0x2 | Binary | バイナリフレーム |
| 0x8 | Close | クローズフレーム |
| 0x9 | Ping | Pingフレーム (ハートビート) |
| 0xA | Pong | Pongフレーム (ハートビート応答) |
クローズステータスコード
| コード | 名称 | 説明 |
|---|---|---|
| 1000 | Normal Closure | 正常クローズ |
| 1001 | Going Away | エンドポイントの離脱 (例: ページナビゲーション) |
| 1002 | Protocol Error | プロトコルエラー |
| 1003 | Unsupported Data | サポートされていないデータ型 |
| 1006 | Abnormal Closure | 異常クローズ (Closeフレーム未送信) |
| 1009 | Message Too Big | メッセージが大きすぎる |
| 1011 | Internal Error | サーバー内部エラー |
フレーム構造 (基本形式)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+-------------------------------+
| Extended payload length continued, if payload len == 127 |
+-------------------------------+-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------+-------------------------------+
重要ポイント:
- FIN: 1=最終フレーム, 0=後続フレームあり
- MASK: クライアント→サーバーは1でなければならない、サーバー→クライアントは0でなければならない
- Opcode: フレームタイプ識別子
- Payload Length: データ長 (0-125は直接表現、126は16ビット使用、127は64ビット使用)
主要用語
| 英語用語 | 日本語訳 | 説明 |
|---|---|---|
| Full-Duplex Communication | 全二重通信 | 双方向同時通信 |
| Opening Handshake | オープニングハンドシェイク | HTTPからWebSocketへのアップグレードプロセス |
| Closing Handshake | クロージングハンドシェイク | 正常な接続クローズプロセス |
| Frame | フレーム | データ転送の基本単位 |
| Message | メッセージ | 1つ以上のフレームで構成 |
| Masking | マスキング | クライアントデータは必須マスク (セキュリティ機構) |
| Fragmentation | フラグメンテーション | 大きなメッセージを複数フレームで転送 |
WebSocketプロトコル実装ガイド (RFC 6455)
このドキュメントは、RFC 6455の詳細な技術ガイドおよび実装リファレンスであり、プロトコルの説明、コード例、ベストプラクティスを含んでいます。RFC公式章の翻訳については、各章のドキュメントを参照してください。
RFC 6455 - WebSocketプロトコル
Internet Engineering Task Force (IETF)
Request for Comments: 6455
カテゴリ: Standards Track
著者:
I. Fette (Google Inc.)
A. Melnikov (Isode Ltd.)
発行日: 2011年12月
このメモランダムのステータス
これはInternet Standards Trackドキュメントです。
このドキュメントは、Internet Engineering Task Force (IETF) の成果物であり、IETFコミュニティのコンセンサスを表しています。
著作権表示
Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved.
概要
WebSocketプロトコル (WebSocket Protocol) は、単一のTCP接続上でクライアントとサーバー間の全二重通信 (Full-Duplex Communication) を可能にします。WebSocketプロトコルは、WebブラウザおよびWebサーバーでの実装を目的として設計されていますが、任意のクライアントまたはサーバーアプリケーションで使用できます。
WebSocketプロトコルは、TCPベースの独立したプロトコルです。HTTPとの唯一の関係は、そのハンドシェイク (Handshake) がHTTPサーバーによってアップグレードリクエスト (Upgrade Request) として解釈されることです。
設計により、WebSocketプロトコルは既存のHTTPインフラストラクチャ上で動作することを目指しているため、HTTPポート80および443を使用し、HTTPプロキシおよび中間装置をサポートします。これは、ある程度の複雑さを意味する場合でもそうです。
目次
- 1. 導入 (Introduction)
- 2. 適合性要件 (Conformance Requirements)
- 3. WebSocket URI
- 4. オープニングハンドシェイク (Opening Handshake)
- 5. データフレーミング (Data Framing)
- 6. データの送受信 (Sending and Receiving Data)
- 7. 接続のクローズ (Closing the Connection)
- 8. エラー処理 (Error Handling)
- 9. 拡張 (Extensions)
- 10. セキュリティに関する考慮事項 (Security Considerations)
- 11. IANAに関する考慮事項 (IANA Considerations)
- 12. 他の仕様からのWebSocketプロトコルの使用
- 13. 謝辞
- 14. 参考文献
WebSocketコア用語集
基本概念
| 英語用語 | 日本語訳 | 説明 |
|---|---|---|
| WebSocket Protocol | WebSocketプロトコル | 単一のTCP接続上で全二重通信を可能にするプロトコル |
| Full-Duplex Communication | 全二重通信 | 双方向同時通信 |
| Opening Handshake | オープニングハンドシェイク | WebSocket接続を確立するためのHTTPアップグレードプロセス |
| Closing Handshake | クロージングハンドシェイク | WebSocket接続を正常にクローズするためのプロセス |
| Frame | フレーム | WebSocketデータ転送の基本単位 |
| Message | メッセージ | 1つ以上のフレームで構成される完全なアプリケーションデータ |
| Client | クライアント | WebSocket接続を開始する側 (通常はブラウザ) |
| Server | サーバー | WebSocket接続を受け入れる側 |
| Endpoint | エンドポイント | クライアントまたはサーバー |
| Connection | 接続 | クライアントとサーバー間のWebSocket接続 |
ハンドシェイク関連
| 英語用語 | 日本語訳 | 説明 |
|---|---|---|
| Upgrade Request | アップグレードリクエスト | WebSocketへのHTTPアップグレードリクエスト |
| Sec-WebSocket-Key | WebSocketキー | クライアントが送信するランダムキー |
| Sec-WebSocket-Accept | WebSocket受け入れ | サーバーが返す検証キー |
| Sec-WebSocket-Protocol | WebSocketサブプロトコル | 交渉されたアプリケーション層サブプロトコル |
| Sec-WebSocket-Extensions | WebSocket拡張 | 交渉されたプロトコル拡張 |
| Sec-WebSocket-Version | WebSocketバージョン | プロトコルバージョン番号 (現在は13) |
| Origin | オリジン | 接続を開始するWebページの発信元 |
フレーム構造関連
| 英語用語 | 日本語訳 | 説明 |
|---|---|---|
| FIN | FIN / 終了ビット | これがメッセージの最後のフレームであることを示す |
| RSV | RSV / 予約ビット | 拡張用に予約されたフラグビット |
| Opcode | オペコード / 操作コード | フレームのタイプを定義 |
| Mask | マスク | クライアントからサーバーへのデータはマスク必須 |
| Masking-key | マスキングキー | データマスキング用の32ビットキー |
| Payload Length | ペイロード長 | データ長 |
| Payload Data | ペイロードデータ | 実際に転送されるデータ |
| Extension Data | 拡張データ | 拡張によって交渉された追加データ |
| Application Data | アプリケーションデータ | アプリケーション層の実際のデータ |
フレームタイプ
| 英語用語 | 日本語訳 | オペコード | 説明 |
|---|---|---|---|
| Continuation Frame | 継続フレーム | 0x0 | メッセージの後続フレーム |
| Text Frame | テキストフレーム | 0x1 | UTF-8エンコードされたテキストデータ |
| Binary Frame | バイナリフレーム | 0x2 | バイナリデータ |
| Close Frame | クローズフレーム | 0x8 | 接続クローズ用制御フレーム |
| Ping Frame | Pingフレーム | 0x9 | ハートビート検出リクエスト |
| Pong Frame | Pongフレーム | 0xA | ハートビート検出レスポンス |
| Control Frame | 制御フレーム | 0x8-0xF | 接続制御用フレーム |
| Data Frame | データフレーム | 0x1-0x2 | アプリケーションデータ転送用フレーム |
クローズ関連
| 英語用語 | 日本語訳 | 説明 |
|---|---|---|
| Close Code | クローズコード | 接続クローズの理由を示す数値コード |
| Close Reason | クローズ理由 | クローズのテキスト説明 |
| Normal Closure | 正常クローズ | コード1000、目的達成後の正常なクローズ |
| Going Away | 離脱 | コード1001、エンドポイントが離脱 (ページナビゲーションなど) |
| Protocol Error | プロトコルエラー | コード1002、プロトコル違反 |
| Unsupported Data | サポートされないデータ | コード1003、受け入れられないデータタイプを受信 |
| Invalid Frame Payload Data | 無効なフレームペイロードデータ | コード1007、データの不整合 |
| Policy Violation | ポリシー違反 | コード1008、ポリシーの違反 |
| Message Too Big | メッセージが大きすぎる | コード1009、処理するには大きすぎるメッセージ |
| TLS Handshake Failure | TLSハンドシェイク失敗 | コード1015、TLSハンドシェイク失敗 |
ドキュメント構造の説明
セクション1: 導入と概要
- WebSocketの背景とニーズ
- プロトコルの設計目標と原則
- HTTP/TCPとの関係
- セキュリティモデルと設計哲学
セクション2-3: 基本要件
- 適合性要件と用語定義
- WebSocket URIフォーマット (ws:// および wss://)
セクション4: オープニングハンドシェイク (コア)
- クライアントがハンドシェイクを開始する方法
- サーバーがハンドシェイクに応答する方法
- サブプロトコルと拡張の交渉
- 複数バージョンのサポート
セクション5: データフレーミング (コア)
- フレーム構造の詳細説明
- マスキングメカニズム
- 断片化 (大きなメッセージを複数のフレームで転送)
- 制御フレームとデータフレーム
セクション6-7: データ転送と接続クローズ
- メッセージの送受信ルール
- 正常なクローズフロー
- 例外処理
- クローズステータスコード
セクション8-10: 拡張、エラー、およびセキュリティ
- 拡張メカニズム
- エラー処理
- 詳細なセキュリティ考慮事項
WebSocket接続確立フロー
1. クライアントがHTTPアップグレードリクエストを開始
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
2. サーバーがアップグレードで応答
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
3. 接続確立、双方向通信開始
Client ←→ Server
↓ ↓
Text/Binary Frames
Ping/Pong Frames
Close Frame
4. 接続をクローズ
Client → Server: Close Frame (Code: 1000)
Server → Client: Close Frame (Code: 1000)
TCP接続をクローズ
ハンドシェイクキー計算
Sec-WebSocket-Acceptの計算方法
// 1. クライアントがランダムなSec-WebSocket-Keyを生成 (Base64エンコードされた16バイトの乱数)
const clientKey = "dGhlIHNhbXBsZSBub25jZQ==";
// 2. マジック文字列 (RFC 6455で定義された固定GUID)
const magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
// 3. 連結してSHA-1ハッシュを計算
const concatenated = clientKey + magicString;
const hash = SHA1(concatenated);
// 4. Base64エンコードでSec-WebSocket-Acceptを取得
const serverAccept = Base64Encode(hash);
// 結果: "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
このメカニズムは以下を保証します:
- サーバーがWebSocketプロトコルを理解している (通常のHTTPサーバーではない)
- キャッシングプロキシが誤った応答を返すのを防ぐ
- 基本的なハンドシェイク検証を提供
WebSocketフレーム構造の詳細
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
フィールドの説明
FIN (1ビット):
- 0 = さらにフレームが続く
- 1 = これがメッセージの最後 (または唯一) のフレーム
RSV1, RSV2, RSV3 (各1ビット):
- 拡張用に予約
- 拡張が交渉されていない場合は0でなければならない
Opcode (4ビット):
- 0x0 = Continuation (継続フレーム)
- 0x1 = Text (テキストフレーム、UTF-8)
- 0x2 = Binary (バイナリフレーム)
- 0x8 = Close (クローズ)
- 0x9 = Ping
- 0xA = Pong
- 0x3-0x7, 0xB-0xF = 予約済み
MASK (1ビット):
- クライアントからサーバーへ: 1でなければならない
- サーバーからクライアントへ: 0でなければならない
Payload Length (7ビット、7+16ビット、または7+64ビット):
- 0-125: 実際の長さ
- 126: 次の16ビットが実際の長さ
- 127: 次の64ビットが実際の長さ
Masking-key (0または4バイト):
- MASK=1の場合、32ビットマスキングキーを含む
Payload Data:
- Extension data + Application data
マスキングメカニズムの説明
なぜマスキングが必要なのか?
セキュリティ上の理由: キャッシュポイズニング攻撃を防ぐため。一部の中間プロキシがWebSocketフレームを誤ってキャッシュする可能性があり、マスキングによりデータが予測不可能であることを保証します。
マスキングアルゴリズム
// クライアントがデータを送信する際
function maskData(data, maskingKey) {
const masked = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
masked[i] = data[i] ^ maskingKey[i % 4];
}
return masked;
}
// サーバーがデータを受信する際 (デコード用に同じアルゴリズムを使用)
function unmaskData(maskedData, maskingKey) {
return maskData(maskedData, maskingKey); // XORは自己逆演算
}
重要なポイント:
- XOR演算 (^) を使用
- キーの長さは4バイト
- キーを循環的に使用
- クライアント→サーバー: マスクが必須
- サーバー→クライアント: マスク禁止
メッセージの断片化 (Fragmentation)
大きなメッセージは複数のフレームで送信できます:
例: 大きなテキストメッセージの送信
Frame 1: FIN=0, Opcode=0x1 (Text), Payload="Hello "
Frame 2: FIN=0, Opcode=0x0 (Continuation), Payload="World"
Frame 3: FIN=1, Opcode=0x0 (Continuation), Payload="!"
最終メッセージ: "Hello World!"
ルール:
- 最初のフレーム: FIN=0, Opcode=データタイプ (0x1または0x2)
- 中間のフレーム: FIN=0, Opcode=0x0 (Continuation)
- 最後のフレーム: FIN=1, Opcode=0x0 (Continuation)
- 制御フレームは断片化できないし、断片化されたデータフレームの間に挿入できる
制御フレームの詳細
Closeフレーム (0x8)
構造:
+--------+--------+------------------+
| Code | Reason |
| (2バイト) | (UTF-8テキスト) |
+--------+--------+------------------+
例:
Close Code: 1000 (正常クローズ)
Close Reason: "Going away"
よく使用されるクローズコード:
- 1000: Normal Closure (正常クローズ)
- 1001: Going Away (エンドポイントが離脱、ページナビゲーションなど)
- 1002: Protocol Error (プロトコルエラー)
- 1003: Unsupported Data (サポートされないデータタイプ)
- 1006: Abnormal Closure (異常クローズ、Closeフレーム未送信)
- 1009: Message Too Big (メッセージが大きすぎる)
- 1011: Internal Server Error (サーバー内部エラー)
Pingフレーム (0x9)
- クライアントまたはサーバーから送信可能
- ハートビート検出に使用 (接続をアクティブに保つ)
- アプリケーションデータを運ぶことができる (最大125バイト)
- 受信者は必ずPongフレームで応答しなければならない
Pongフレーム (0xA)
- Pingフレームへの応答に使用
- Pingフレームと同じペイロードを含まなければならない
- 能動的に送信することもできる (単方向ハートビート)
クローズフロー
正常クローズ (Clean Close)
1. イニシエーターがCloseフレームを送信
Client → Server: Close Frame (Code: 1000)
2. 受信者がCloseフレームで応答
Server → Client: Close Frame (Code: 1000)
3. イニシエーターがTCP接続をクローズ
Client: TCP接続をクローズ
4. 受信者もTCP接続をクローズ
Server: TCP接続をクローズ
異常クローズ
- TCP接続が突然切断 (Closeフレームなし)
- 無効なフレームデータを受信
- 応答なしでタイムアウト
- プロトコルルール違反
ステータスコード: 1006 (Abnormal Closure) - このコードはCloseフレームで送信されず、報告のみに使用
WebSocket URIフォーマット
ws:// (非暗号化)
ws://example.com/socket
ws://example.com:8080/chat
ws://192.168.1.1/data
- デフォルトポート: 80
- http:// のセキュリティレベルと同等
wss:// (TLS暗号化)
wss://example.com/socket
wss://secure.example.com:443/chat
- デフォルトポート: 443
- https:// のセキュリティレベルと同等
- 本番環境では wss:// の使用を強く推奨
サブプロトコル (Subprotocol)
WebSocketはトランスポート層プロトコルであり、サブプロトコルはアプリケーション層のメッセージフォーマットを定義します:
クライアントリクエスト:
Sec-WebSocket-Protocol: chat, superchat
サーバーレスポンス:
Sec-WebSocket-Protocol: chat
確立された接続は"chat"サブプロトコルを使用
一般的なサブプロトコル:
- STOMP: Simple Text Oriented Messaging Protocol
- MQTT: Message Queuing Telemetry Transport
- WAMP: Web Application Messaging Protocol
- カスタムアプリケーションプロトコル
拡張 (Extensions)
拡張はWebSocket機能を強化できます:
クライアントリクエスト:
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
サーバーレスポンス:
Sec-WebSocket-Extensions: permessage-deflate
よく使用される拡張:
- permessage-deflate: メッセージ圧縮 (RFC 7692)
- permessage-bzip2: Bzip2圧縮
- カスタム拡張
セキュリティ考慮事項の要点
1. オリジン検証 (Origin Validation)
// サーバー側のオリジン検証
const allowedOrigins = ['https://example.com', 'https://app.example.com'];
const origin = request.headers['origin'];
if (!allowedOrigins.includes(origin)) {
// 接続を拒否
response.status(403).send('Forbidden');
}
2. TLS暗号化
- 本番環境では wss:// を使用しなければならない
- 中間者攻撃を防ぐ
- データの機密性と完全性を保護
3. 認証と認可
方法1: ハンドシェイク時にCookieを介して認証
GET /socket HTTP/1.1
Cookie: session=abc123
方法2: サブプロトコルを介してトークンを渡す
ws://example.com/socket?token=jwt_token
方法3: 接続後の最初のメッセージで認証情報を運ぶ
4. レート制限
- 接続数を制限 (DoS防止)
- メッセージサイズを制限
- メッセージ頻度を制限
5. 入力検証
- UTF-8エンコーディングを検証 (テキストフレーム)
- メッセージフォーマットを検証
- インジェクション攻撃を防ぐ
実装のベストプラクティス
クライアント (ブラウザ)
// 1. WebSocket接続を作成
const ws = new WebSocket('wss://example.com/socket', ['chat']);
// 2. イベントリスナーを登録
ws.addEventListener('open', (event) => {
console.log('接続が確立されました');
ws.send('Hello Server!');
});
ws.addEventListener('message', (event) => {
console.log('メッセージを受信:', event.data);
});
ws.addEventListener('error', (event) => {
console.error('WebSocketエラー:', event);
});
ws.addEventListener('close', (event) => {
console.log('接続がクローズされました', event.code, event.reason);
// 再接続ロジックを実装
if (event.code !== 1000) {
setTimeout(() => reconnect(), 5000);
}
});
// 3. データを送信
ws.send('テキストメッセージ');
ws.send(new Blob(['バイナリデータ']));
ws.send(new ArrayBuffer(8));
// 4. 接続をクローズ
ws.close(1000, '正常クローズ');
サーバー側 (Node.js例)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws, request) => {
// オリジンを検証
const origin = request.headers.origin;
// ...検証ロジック
// ハートビート検出
ws.isAlive = true;
ws.on('pong', () => { ws.isAlive = true; });
// メッセージを受信
ws.on('message', (data) => {
console.log('受信:', data);
// 全クライアントにブロードキャスト
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
// エラー処理
ws.on('error', (error) => {
console.error('エラー:', error);
});
// クローズ
ws.on('close', (code, reason) => {
console.log('接続がクローズされました:', code, reason);
});
});
// ハートビート検出
const interval = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, 30000);
一般的な適用シナリオ
1. リアルタイムチャットアプリケーション
- インスタントメッセージング
- オンラインステータス表示
- タイピングインジケーター
2. リアルタイムコラボレーションツール
- ドキュメント共同編集 (Google Docsなど)
- ホワイトボード共有
- コラボレーティブコードエディタ
3. リアルタイムデータストリーム
- 株価
- スポーツスコア
- IoTデータ
4. オンラインゲーム
- マルチプレイヤーオンラインゲーム
- リアルタイムゲーム状態同期
- 低遅延インタラクション
5. プッシュ通知
- ブラウザプッシュ
- リアルタイムアラート
- システム監視
他の技術との比較
WebSocket vs HTTP Long Polling
| 特性 | WebSocket | Long Polling |
|---|---|---|
| 接続 | 永続的な接続 | 繰り返しHTTPリクエスト |
| レイテンシ | 非常に低い | 高い (HTTPオーバーヘッド) |
| 双方向 | 真の双方向 | 疑似双方向 |
| リソース | 低 (1つの接続) | 高 (複数の接続) |
| 複雑さ | 中程度 | より単純 |
WebSocket vs Server-Sent Events (SSE)
| 特性 | WebSocket | SSE |
|---|---|---|
| 双方向通信 | ✅ 双方向 | ❌ サーバー→クライアントのみ |
| データフォーマット | バイナリまたはテキスト | テキスト (UTF-8) |
| プロトコル | 独立したプロトコル | HTTPベース |
| ブラウザサポート | 広くサポート | 広くサポート (IEを除く) |
| 再接続 | 手動実装 | 自動再接続 |
デバッグツール
ブラウザ開発者ツール
- Chrome DevTools → Network → WS
- フレームの送受信を表示
- 接続状態を表示
コマンドラインツール
# wscat (Node.js)
npm install -g wscat
wscat -c ws://echo.websocket.org
# websocat (Rust)
websocat ws://echo.websocket.org
オンラインテストツール
- websocket.org Echo Test
- Hoppscotch (旧Postwoman)
- Firecamp
リファレンスリソース
関連RFC標準
- RFC 6455: WebSocketプロトコル (このドキュメント)
- RFC 7692: WebSocket圧縮拡張
- RFC 8441: HTTP/2上のWebSocketブートストラッピング
- RFC 8307: WebSocket用Well-Known URI
推奨実装ライブラリ
JavaScript (ブラウザ):
- ネイティブWebSocket API
Node.js:
- ws (軽量)
- Socket.IO (機能豊富、自動フォールバック)
- uWebSockets.js (高性能)
Python:
- websockets (asyncio)
- ws4py
- Tornado
Java:
- Java WebSocket API (JSR 356)
- Netty
- Spring WebSocket
Go:
- gorilla/websocket
- nhooyr/websocket
次のステップの学習提案
- 基礎: WebSocketハンドシェイクとフレーム構造を理解
- 実践: シンプルなチャットアプリケーションを実装
- 応用: サブプロトコルと拡張を学習
- 最適化: ハートビート、再接続、エラー処理を実装
- セキュリティ: セキュリティ考慮事項とベストプラクティスを深く理解
まとめ
WebSocketプロトコルはWebリアルタイム通信の基盤です:
- 正確性: 双方向通信の正確な実装
- 伝達性: 明確なプロトコル仕様
- 優雅性: エレガントな設計と実装
コアバリュー:
- 🔄 真の全二重通信
- ⚡ 低遅延リアルタイムデータ転送
- 📦 軽量フレームプロトコル
- 🔐 組み込みセキュリティメカニズム
最適な使用シナリオ:
- リアルタイムチャット
- コラボレーティブ編集
- リアルタイムゲーム
- リアルタイムデータストリーム
- プッシュ通知
関連RFC:
- RFC 6455: WebSocketプロトコル (このドキュメント)
- RFC 7692: WebSocket圧縮拡張
- RFC 8441: HTTP/2上のWebSocketブートストラッピング