WebSocketとは
WebSocketは、サーバーとクライアント間で双方向リアルタイム通信を可能にする通信プロトコルです。
従来のHTTP通信との根本的な違いを理解することから始めましょう。
HTTP通信 vs WebSocket通信
HTTP通信(従来の方式)
クライアント → サーバー: リクエスト送信
クライアント ← サーバー: レスポンス受信
【通信終了】
再度やり取りしたい場合:
クライアント → サーバー: 新しいリクエスト送信
特徴:
- 一問一答形式
- クライアントからしか通信開始できない
- 毎回接続を確立・切断
WebSocket通信
【最初に一度だけ接続確立】
クライアント ⇄ サーバー: 常時接続維持
以降はいつでも:
クライアント → サーバー: メッセージ送信
クライアント ← サーバー: メッセージ受信
特徴:
- 双方向通信
- サーバーからもデータ送信可能
- 接続を維持し続ける
WebSocketが必要な場面
適用例
- チャットアプリ: リアルタイムメッセージ交換
- ゲーム: プレイヤー間のリアルタイム状態同期
- 株価表示: 価格の即座更新
- 協調編集: Google Docsのようなリアルタイム編集
- 通知システム: サーバーからの即座プッシュ通知
HTTP通信では困難な理由
HTTPでリアルタイム風を実現するにはポーリングが必要:
// 悪い例:HTTPポーリング
setInterval(() => {
fetch('/api/messages') // 1秒ごとにサーバーに問い合わせ
.then(response => response.json())
.then(data => updateUI(data))
}, 1000)
問題点:
- 無駄なリクエストが大量発生
- サーバー負荷が高い
- 真のリアルタイム性がない(遅延がある)
WebSocketの仕組み(技術的詳細)
1. 接続確立過程
1. クライアント: HTTP接続でWebSocketハンドシェイクリクエスト
2. サーバー: WebSocketプロトコルへアップグレード応答
3. 以降: WebSocket通信でデータ交換
2. データフレーム構造
WebSocketでは小さなデータ単位(フレーム)でやり取り:
- テキストフレーム(JSON、文字列)
- バイナリフレーム(画像、ファイル等)
- 制御フレーム(接続維持、切断等)
実装例(基本パターン)
クライアント側(JavaScript)
// WebSocket接続確立
const socket = new WebSocket('ws://localhost:8080')
// 接続成功時
socket.onopen = () => {
console.log('WebSocket接続確立')
socket.send('Hello Server!')
}
// メッセージ受信時
socket.onmessage = (event) => {
console.log('受信:', event.data)
}
// エラー発生時
socket.onerror = (error) => {
console.error('WebSocketエラー:', error)
}
// 接続切断時
socket.onclose = () => {
console.log('WebSocket接続切断')
}
サーバー側(Node.js + ws)
const WebSocket = require('ws')
const server = new WebSocket.Server({ port: 8080 })
server.on('connection', (socket) => {
console.log('クライアント接続')
// メッセージ受信時
socket.on('message', (message) => {
console.log('受信:', message.toString())
// 全クライアントにブロードキャスト
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(`ブロードキャスト: ${message}`)
}
})
})
// 切断時
socket.on('close', () => {
console.log('クライアント切断')
})
})