WebSocket

API | IT用語集

この用語をシェア

WebSocketとは

WebSocketは、Webブラウザとサーバー間でリアルタイムな双方向通信を実現するプロトコルです。RFC 6455として標準化されており、HTTPベースのリクエスト・レスポンスモデルとは異なり、一度接続を確立すると、クライアントとサーバーの両方がいつでも自由にデータを送信できます。

WebSocketの主要な特徴

  • 双方向通信:クライアントとサーバーが同時にデータを送信可能
  • リアルタイム:低遅延でのデータ交換が可能
  • 持続的接続:一度接続すると接続が維持される
  • 軽量:HTTPヘッダーのオーバーヘッドがない
  • ファイアウォール対応:HTTPポート(80/443)を使用

WebSocket vs HTTP

特徴 WebSocket HTTP
通信方式 双方向 リクエスト・レスポンス
接続 持続的 ステートレス
オーバーヘッド 低い 高い
リアルタイム性 高い 低い
キャッシュ 不可 可能

WebSocketの接続プロセス

1. ハンドシェイク(Handshake)

WebSocketは、HTTPアップグレードリクエストから始まります。

クライアントからのリクエスト

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://example.com

サーバーからのレスポンス

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

2. データ交換フェーズ

接続が確立されると、フレームベースでデータを交換します。

WebSocketフレーム構造

  0               1               2               3
  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |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 ...                |
 +---------------------------------------------------------------+

WebSocket Opcodeの種類

Opcode 意味 説明
0x0 継続フレーム 分割されたメッセージの続き
0x1 テキストフレーム UTF-8テキストデータ
0x2 バイナリフレーム バイナリデータ
0x8 接続終了 接続を終了する
0x9 Ping 接続確認
0xA Pong Pingへの応答

WebSocketの実装例

クライアント(JavaScript)

// WebSocket接続の確立
const socket = new WebSocket('ws://localhost:8080');

// 接続が開かれたときの処理
socket.onopen = function(event) {
    console.log('WebSocket接続が開かれました');
    
    // メッセージを送信
    socket.send('Hello Server!');
};

// メッセージを受信したときの処理
socket.onmessage = function(event) {
    console.log('受信したメッセージ:', event.data);
    
    // JSONメッセージの解析
    try {
        const data = JSON.parse(event.data);
        console.log('パースされたデータ:', data);
    } catch (e) {
        console.log('テキストメッセージ:', event.data);
    }
};

// エラーが発生したときの処理
socket.onerror = function(error) {
    console.error('WebSocketエラー:', error);
};

// 接続が閉じられたときの処理
socket.onclose = function(event) {
    console.log('WebSocket接続が閉じられました');
    console.log('コード:', event.code);
    console.log('理由:', event.reason);
    
    // 再接続の試行
    setTimeout(() => {
        console.log('再接続を試行します...');
        // 再接続のロジック
    }, 5000);
};

// JSONメッセージの送信
function sendJSON(data) {
    if (socket.readyState === WebSocket.OPEN) {
        socket.send(JSON.stringify(data));
    }
}

// 接続を閉じる
function closeConnection() {
    socket.close(1000, 'ユーザーによる切断');
}

サーバー(Node.js + ws)

const WebSocket = require('ws');

// WebSocketサーバーの作成
const wss = new WebSocket.Server({ port: 8080 });

// 接続されたクライアントの管理
const clients = new Set();

console.log('WebSocketサーバーがポート8080で起動しました');

// クライアントが接続したときの処理
wss.on('connection', function connection(ws, req) {
    console.log('新しいクライアントが接続しました');
    
    // クライアントリストに追加
    clients.add(ws);
    
    // 接続確認メッセージを送信
    ws.send(JSON.stringify({
        type: 'welcome',
        message: 'WebSocketサーバーへようこそ!',
        timestamp: new Date().toISOString()
    }));
    
    // メッセージを受信したときの処理
    ws.on('message', function incoming(data) {
        console.log('受信したメッセージ:', data.toString());
        
        try {
            const message = JSON.parse(data);
            
            // すべてのクライアントにブロードキャスト
            broadcastMessage({
                type: 'broadcast',
                data: message,
                timestamp: new Date().toISOString()
            });
            
        } catch (e) {
            // テキストメッセージの場合
            broadcastMessage({
                type: 'text',
                message: data.toString(),
                timestamp: new Date().toISOString()
            });
        }
    });
    
    // 接続が閉じられたときの処理
    ws.on('close', function close() {
        console.log('クライアントが切断しました');
        clients.delete(ws);
    });
    
    // エラーが発生したときの処理
    ws.on('error', function error(err) {
        console.error('WebSocketエラー:', err);
        clients.delete(ws);
    });
    
    // 定期的なPing送信
    const pingInterval = setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
            ws.ping();
        } else {
            clearInterval(pingInterval);
        }
    }, 30000);
});

// 全クライアントにメッセージをブロードキャスト
function broadcastMessage(message) {
    const data = JSON.stringify(message);
    
    clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
            client.send(data);
        }
    });
}

サーバー(Python + websockets)

import asyncio
import websockets
import json
import logging

# ログ設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 接続されたクライアントの管理
connected_clients = set()

async def handle_client(websocket, path):
    """クライアント接続の処理"""
    logger.info(f"新しいクライアントが接続しました: {websocket.remote_address}")
    
    # クライアントリストに追加
    connected_clients.add(websocket)
    
    try:
        # 接続確認メッセージを送信
        await websocket.send(json.dumps({
            'type': 'welcome',
            'message': 'WebSocketサーバーへようこそ!',
            'clients_count': len(connected_clients)
        }))
        
        # メッセージを受信し続ける
        async for message in websocket:
            logger.info(f"受信したメッセージ: {message}")
            
            try:
                # JSONメッセージの解析
                data = json.loads(message)
                
                # すべてのクライアントにブロードキャスト
                await broadcast_message({
                    'type': 'broadcast',
                    'data': data,
                    'from': str(websocket.remote_address),
                    'clients_count': len(connected_clients)
                })
                
            except json.JSONDecodeError:
                # テキストメッセージの場合
                await broadcast_message({
                    'type': 'text',
                    'message': message,
                    'from': str(websocket.remote_address),
                    'clients_count': len(connected_clients)
                })
                
    except websockets.exceptions.ConnectionClosed:
        logger.info(f"クライアントが切断しました: {websocket.remote_address}")
    except Exception as e:
        logger.error(f"エラーが発生しました: {e}")
    finally:
        # クライアントリストから削除
        connected_clients.discard(websocket)

async def broadcast_message(message):
    """全クライアントにメッセージをブロードキャスト"""
    if not connected_clients:
        return
    
    data = json.dumps(message)
    await asyncio.gather(
        *[client.send(data) for client in connected_clients],
        return_exceptions=True
    )

# WebSocketサーバーの起動
async def main():
    logger.info("WebSocketサーバーをポート8080で起動します...")
    
    async with websockets.serve(handle_client, "localhost", 8080):
        logger.info("WebSocketサーバーが起動しました")
        await asyncio.Future()  # 永続的に実行

if __name__ == "__main__":
    asyncio.run(main())

WebSocketの活用例

1. リアルタイムチャットアプリ

  • 用途:インスタントメッセージング
  • 特徴:即座のメッセージ配信
  • 実装:Socket.IO, WebSocket API

2. オンラインゲーム

  • 用途:マルチプレイヤーゲーム
  • 特徴:低遅延でのゲーム状態同期
  • 実装:カスタムプロトコル

3. ライブ配信・動画通話

  • 用途:ストリーミング、ビデオ会議
  • 特徴:リアルタイムメディア配信
  • 実装:WebRTC + WebSocket

4. 金融取引システム

  • 用途:株価、為替レートの配信
  • 特徴:高頻度でのデータ更新
  • 実装:専用プロトコル

WebSocketライブラリ・フレームワーク

JavaScript(クライアント)

  • WebSocket API:ブラウザ標準API
  • Socket.IO:フォールバック機能付きライブラリ
  • ws:Node.js用WebSocketライブラリ

サーバーサイド

  • Node.js:ws、Socket.IO
  • Python:websockets、tornado
  • Java:Java WebSocket API、Netty
  • Go:gorilla/websocket
  • C#:SignalR

WebSocketのセキュリティ

セキュリティ考慮事項

  • Origin検証:適切なOriginからの接続のみ許可
  • 認証・認可:トークンベースの認証実装
  • 入力検証:受信データの検証
  • レート制限:メッセージ頻度の制限
  • WSS使用:SSL/TLS暗号化

WSS(WebSocket Secure)

// 暗号化されたWebSocket接続
const socket = new WebSocket('wss://example.com/socket');

// 証明書の検証
socket.onopen = function(event) {
    console.log('セキュアな接続が確立されました');
};

WebSocketの制限事項

  • ファイアウォール:一部のプロキシやファイアウォールでブロック
  • 接続数制限:サーバーリソースによる制限
  • メッセージサイズ:大きなメッセージの処理負荷
  • ネットワーク切断:接続の予期せぬ切断
  • メモリ使用:持続的接続によるメモリ消費

WebSocketの代替技術

Server-Sent Events (SSE)

  • 用途:サーバーからクライアントへの一方向通信
  • 特徴:HTTPベース、自動再接続
  • 制限:クライアントからサーバーへの通信不可

Long Polling

  • 用途:疑似リアルタイム通信
  • 特徴:HTTPベース、フォールバック対応
  • 制限:オーバーヘッドが大きい

WebRTC

  • 用途:P2P通信、メディアストリーミング
  • 特徴:ブラウザ間直接通信
  • 制限:設定が複雑

WebSocketのベストプラクティス

  • 再接続機能:ネットワーク切断時の自動再接続
  • ハートビート:定期的なPing/Pongで接続確認
  • エラーハンドリング:適切なエラー処理
  • メッセージキューイング:送信失敗時のメッセージ保持
  • リソース管理:適切な接続数制限

WebSocketの今後

  • HTTP/3対応:QUIC プロトコルベースの改良
  • WebTransport:新しいリアルタイム通信API
  • WebAssembly統合:高性能アプリケーション
  • エッジコンピューティング:CDN でのWebSocket対応

関連技術

  • Socket.IO:WebSocketライブラリ
  • SignalR:Microsoft のリアルタイム通信ライブラリ
  • WebRTC:リアルタイム通信API
  • Server-Sent Events:一方向リアルタイム通信

関連Webサイト

この用語についてもっと詳しく

WebSocketに関するご質問や、システム導入のご相談など、お気軽にお問い合わせください。

カテゴリ

API IT用語集