WebSocketは、クライアントとサーバー間でリアルタイムのデータ交換を行うための永続的接続を確立する全二重通信プロトコルです。従来のHTTPリクエストとは異なり、このプロトコルは単一の接続を確立し、繰り返しのハンドシェイクなしで双方向伝送に使用します。Mozilla Developer Network(2025)によると、WebSocketはリアルタイムアプリケーションにおいてHTTPポーリングと比較してレイテンシを最大50%削減します。
重要なポイント
WebSocketはTCP上で動作し、クライアントとサーバー間で全二重チャネルを提供する通信プロトコルです。2011年にIETFによってRFC 6455として標準化され、すべての最新ブラウザ、モバイルプラットフォーム、サーバーフレームワークでサポートされています。
クライアントがリクエストを開始してレスポンスを受け取るHTTPとは異なり、WebSocketは接続確立後、両側がいつでもメッセージを送信できます。これにより、即時配信が必要なシナリオ(チャット、通知、共同ドキュメント編集)に最適です。
WebSocketプロトコルは初期ハンドシェイクにHTTPポート80またはHTTPSポート443を使用し、その後最小限のヘッダー(HTTPの800+バイトに対してわずか2バイト)で独自のプロトコルに切り替えます。この機能により、多数のメッセージを扱う際に大幅なパフォーマンス上の利点が得られます。
WebSocket接続はHTTPアップグレードリクエスト(Upgrade)で始まり、その後バイナリフレーム形式に切り替わります。フレームサイズは2バイトから2^63バイトまでで、短いテキストメッセージと大きなバイナリデータの両方を伝送できます。プロトコルはメッセージの断片化、クライアントからサーバーへのデータマスキング、接続維持のためのping/pongをサポートしています。
WebSocket接続の確立プロセスは、ハンドシェイクとデータ転送の2段階で構成されます。ハンドシェイク段階では、クライアントがUpgrade:websocketヘッダー付きのHTTPリクエストを送信し、サーバーがステータス101 Switching Protocolsでプロトコル切り替えを確認します。その後、接続は全二重伝送モードになります。
WebSocketの各メッセージはフレームに分割されます。フレームにはopcode(テキスト、バイナリデータ、クローズ、ping/pong)、ペイロード長、クライアントからのデータのマスキングキーが含まれます。フレームは断片化可能で、制御フレーム(ping/pong)はメッセージ断片の間に送信でき、長時間の転送中の接続タイムアウトを防ぎます。
const ws = new WebSocket('wss://example.com/chat')
ws.addEventListener('open', () => {
console.log('接続が確立されました')
ws.send('こんにちは、サーバー!')
})
ws.addEventListener('message', (event) => {
console.log('受信しました:', event.data)
})
ws.addEventListener('close', () => {
console.log('接続が閉じられました')
})
上記の例では、クライアントが安全なURL wss://を指定してWebSocketオブジェクトを作成します。接続が開かれた後、ウェルカムメッセージが送信され、メッセージハンドラがサーバーからの応答を受信します。クローズ時にクローズハンドラが起動します。これはネットワーク中断時の再接続のために重要です。
WebSocketとHTTPの主な違いは対話モデルにあります。HTTPはリクエスト-レスポンス方式で動作します。クライアントがリクエストを開始し、サーバーがレスポンスを返し、接続が閉じられます。一方、WebSocketは永続的なチャネルを確立し、両側がいつでも伝送を開始できます。
低レイテンシと一定のデータストリームを必要とするアプリケーションでは、WebSocketの方がはるかに効率的です。HTTP Long Polling(サーバーがデータが利用可能になるまでリクエストを開いたままにする代替手段)は、サーバーに過剰な負荷をかけ、複数の同時接続によりメモリ消費を増加させます。
| パラメータ | WebSocket | HTTP |
|---|---|---|
| モデル | 全二重 | リクエスト-レスポンス |
| ヘッダー | 2〜14バイト | 400〜800バイト |
| 永続的接続 | はい、単一 | いいえ、リクエストごとに新規 |
| レイテンシ | 低い(1〜5ミリ秒) | 高い(50〜200ミリ秒) |
| プロトコル | ws:// または wss:// | http:// または https:// |
High Performance Browser Networking(Grigorik、O'Reilly)によると、WebSocketはリアルタイムシナリオにおいてHTTP Long Pollingと比較してネットワークレイテンシを40〜60%削減し、繰り返しハンドシェイクの排除によりサーバー負荷は3〜5分の1に減少します。
低レイテンシと双方向通信により、WebSocketは幅広いアプリケーションで使用されています。主なシナリオは、インスタントメッセージング、ゲームの状態同期、金融システムのマーケットデータ伝送です。
WebSocketはチャットアプリケーションの事実上の標準となっています。Slack、Telegram Web、WhatsApp Webなどのプラットフォームは、WebSocketを使用してメッセージを即座に配信します。プロトコルは単一チャネルを通じてテキストメッセージとファイルの両方を送信でき、ping/pongメカニズムにより非アクティブ期間中も接続をアクティブに保ちます。
マルチプレイヤーブラウザゲームやモバイルゲームでは、プレイヤーの状態を同期するために最小限のレイテンシが必要です。WebSocketはHTTPリクエストの遅延なく、座標、アクション、イベントをリアルタイムで伝送します。Socket.IOやColyseusなどのフレームワークは、低レベルのプロトコル操作を抽象化し、自動再接続とルームを追加します。
取引端末やトレーディングプラットフォームは、WebSocketを使用してリアルタイムの相場を受信します。数ミリ秒の遅延が数百万ドルの損失につながる可能性があるため、Binance WebSocket Streams、Coinbase Proなどの金融APIは、マーケットデータにWebSocketインターフェースを提供しています。
モバイル開発では、ネイティブAPI(iOSのURLSessionWebSocketTask、AndroidのOkHttp WebSocket)を通じてWebSocketが使用されます。Flutterにはweb_socket_channelライブラリがあり、React Nativeにはreact-native-websocketがあります。IoTデバイスはテレメトリの送信と制御コマンドの受信にWebSocketを使用します。これはプロトコルが一定のHTTPポーリングよりも消費電力が少ないためです。
Node.jsでwsライブラリ(JavaScriptで最も人気のあるWebSocket実装)を使用したサーバー側の例を見てみましょう。サーバーは接続を受け入れ、メッセージを処理し、接続されているすべてのクライアントにブロードキャストします。
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 8080 })
wss.on('connection', (ws) => {
console.log('新しいクライアントが接続しました')
ws.on('message', (data) => {
console.log('受信しました:', data.toString())
ws.send('サーバーがメッセージを受信しました')
})
ws.on('close', () => {
console.log('クライアントが切断しました')
})
})
console.log('WebSocketサーバーがポート8080で起動しました')
サーバーはポート8080でWebSocket.Serverインスタンスを作成し、接続を待機します。新しいクライアントごとに個別のwsオブジェクトが割り当てられ、サーバーはそれを通じて個別のメッセージを送信できます。すべてのクライアントへのメッセージブロードキャストは、接続の配列を反復処理して実装されます。多数のクライアント(1000以上)がある場合は、Redisベースのスケーリングと自動再接続を追加するSocket.IOなどのクラスタリング対応ライブラリを使用することをお勧めします。
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send('すべての参加者へのメッセージ')
}
})
送信前にreadyStateを確認することが必須です。クライアントが既に切断されている場合、sendを呼び出すとエラーが発生します。WebSocket.OPENフラグは、接続がアクティブでメッセージが配信されることを保証します。
iOSモバイルアプリケーションの場合、WebSocketはiOS 13以降で利用可能なURLSessionWebSocketTaskを通じて実装されます。セッションはwss://プロトコルURLでタスクを作成し、その後sendおよびreceiveメソッドが呼び出されます。メッセージの受信は、前のメッセージを処理した後に次のメッセージを待機する継続的なreceive再帰によって編成でき、再接続なしで一定のデータ受信を保証します。Androidでは、onOpen、onMessage、onClosing、onClosedのコールバックと、接続喪失時の自動再接続を提供するOkHttp WebSocketが使用されます。
モバイルアプリケーションでWebSocketを扱う際は、ライフサイクル管理を考慮することが重要です。アプリがバックグラウンドに移行すると、システムが接続を切断する可能性があります。iOSでは、sceneDidBecomeActiveデリゲートを介してフォアグラウンド復帰時に接続を再確立する必要があります。Androidでは、接続を維持するためにLifecycle-awareコンポーネントまたはServiceを使用する必要があります。さらに、一時的なネットワーク問題時にサーバーに過剰な負荷をかけないよう、再接続に指数バックオフ(試行間隔を1秒から30秒に増加)を実装することをお勧めします。
よくある質問
WebSocketは永続的な全二重接続を確立し、両側がいつでもデータを送信できます。HTTPはリクエスト-レスポンス方式で動作し、各交換に新しい接続と完全なヘッダーが必要です。WebSocketは単一のTCPチャネルとわずか2〜14バイトのヘッダーを使用し、レイテンシを大幅に削減します。
WebSocketは非セキュア接続(ws://)にポート80、セキュア接続(wss://)にポート443を使用します。これにより、追加設定なしでほとんどのプロキシサーバーや企業ファイアウォールを通過できます。TLS暗号化のため、本番環境ではポート443が推奨されます。
はい、WebSocketはすべてのモバイルプラットフォームでサポートされています。iOSではネイティブのURLSessionWebSocketTaskクラスがiOS 13以降で利用可能です。AndroidではOkHttp WebSocketクラスと標準のjava.net.WebSocketがあります。React Nativeにはreact-native-websocketライブラリがあります。
WebSocket SecureはTLS上で動作するプロトコルのセキュアバージョンです。すべてのデータはHTTPSと同様に暗号化されます。本番アプリケーションでは、特にWebSocketを介した認証トークンや個人データの送信時にWSSが必須です。
主な代替手段は、HTTP Long Polling(サーバーがリクエストを開いたままにする)、Server-Sent Events(サーバーからの単方向ストリーム)、WebRTC Data Channel(ピアツーピア通信)です。Server-Sent Eventsは実装は簡単ですが、クライアントからサーバーへの送信をサポートしていません。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。