3.

WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門

編集
この記事の要点
  • WebSocket は 1 本の TCP 接続上で全二重 (双方向) のリアルタイム通信を行うプロトコル。サーバからクライアントへ自発的にデータを送れる
  • 最初は HTTP として接続し、Upgrade ヘッダでプロトコルを切り替える (ハンドシェイク)。以降は HTTP ではなく WebSocket フレームでやり取りする
  • URL スキームは ws:// (平文) と wss:// (TLS 暗号化) の 2 つ。本番では wss が基本
  • チャット・通知・株価/スコアのライブ更新・共同編集・オンラインゲームなど、低遅延の双方向通信に使われる
  • 接続が生きているかを確認するため、ping/pong フレームによるハートビートで死活監視・自動再接続を組むのが定石

概要

WebSocket は、1 本の TCP 接続の上で、クライアントとサーバが双方向 (全二重) に、かつリアルタイムにデータをやり取りするためのプロトコルです (RFC 6455)。通常の HTTP は「クライアントが要求し、サーバが応答する」という一方向のやり取りの繰り返しで、サーバ側から自発的にデータを送ることができません。WebSocket はこの制約を取り払い、サーバからクライアントへいつでも push できる「つなぎっぱなしの通信路」を提供します。親セクションは Web通信プロトコル です。

仕組み

WebSocket 接続は、まず通常の HTTP リクエストとして始まります。クライアントは Upgrade: websocketConnection: Upgrade ヘッダを付けてリクエストし、サーバが 101 Switching Protocols で応答すると、その TCP 接続はそのまま WebSocket 通信路へ切り替わります。これを WebSocket ハンドシェイク と呼びます。

  • アップグレード: HTTP から WebSocket へ昇格するため、既存の 80/443 ポートと HTTP インフラ (プロキシ・ロードバランサ) をそのまま活用できます。
  • フレーム単位の双方向通信: ハンドシェイク後は HTTP のリクエスト/レスポンスではなく、軽量な「フレーム」を双方向に送り合います。テキストフレームとバイナリフレームがあります。
  • ハートビート: 接続が生きているか確認するため ping フレームを送り、相手が pong を返します。無応答なら切れたとみなして再接続します。

URL スキームは 2 種類あり、平文の ws:// と TLS で暗号化された wss:// があります。HTTP に対する HTTPS と同じ関係で、本番環境では盗聴・改ざんを防ぐため wss:// を使うのが基本です。

実用例

ブラウザ標準の WebSocket API を使うと、数行でサーバとリアルタイム通信できます。下記は接続し、メッセージを送受信し、ハートビートを送る最小例です。

// ブラウザ側 (JavaScript)
const ws = new WebSocket("wss://example.com/chat");

ws.onopen = () => {
  console.log("接続しました");
  ws.send(JSON.stringify({ type: "join", room: "general" }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log("受信:", msg);
};

ws.onclose = () => console.log("切断されました");
ws.onerror = (e) => console.error("エラー", e);

// ハートビート: 30 秒ごとに ping 代わりのメッセージを送る
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "ping" }));
  }
}, 30000);

サーバ側は Node.js の ws ライブラリ、Python の websockets、Go の gorilla/websocket などで実装します。接続中のクライアント一覧を保持し、誰かの発言を全員に配信 (ブロードキャスト) するのが典型的なチャット実装です。

主な用途

  • チャット・メッセージング: 双方向の即時配信で、リロードなしにメッセージが届く。
  • リアルタイム通知: サーバ発生イベント (いいね・コメント・アラート) を即座に push する。
  • ライブ更新: 株価・スポーツのスコア・ダッシュボードの数値をリアルタイムに反映する。
  • 共同編集・オンラインゲーム: 複数ユーザの操作を低遅延で同期する。

HTTP ポーリングとの比較

方式サーバ→クライアント push接続遅延オーバーヘッド
ポーリング不可 (定期的に問い合わせ)毎回張り直し大きい大 (毎回ヘッダ)
ロングポーリング擬似的に可応答ごとに張り直し
WebSocket可 (全二重)つなぎっぱなし小さい小 (軽量フレーム)
SSE (Server-Sent Events)可 (サーバ→クライアントのみ)つなぎっぱなし小さい

注意点

  • 本番は wss 必須: ws:// は平文で盗聴・改ざんに弱い。HTTPS ページからは混在コンテンツ扱いで ws:// がブロックされるため wss:// を使う。
  • 切断と再接続の設計: モバイルやスリープで接続は容易に切れる。ハートビートで検知し、指数バックオフで自動再接続する仕組みが要る。
  • スケールアウトの難しさ: 接続が状態を持つため、複数サーバに分散すると「どのサーバに誰が繋がっているか」の共有が必要 (Redis pub/sub など)。
  • プロキシ/LB の対応: 一部の中継機器は長時間のアイドル接続を切る。タイムアウト設定やハートビート間隔の調整が要る。
  • 要求-応答で足りるなら不要: 単発の取得なら通常の HTTP/2 で十分。常時接続のコストを払う価値があるかを見極める。

関連リンク

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. HTTP/2
  2. HTTP/3(QUIC)
  3. WebSocket
  4. gRPC
  5. WebRTC

最近更新/作成されたページ