<CodeLearn/>
WebSocket レッスン1

WebSocketの基本

HTTPとの違い、ハンドシェイク、全二重通信の仕組みを学ぼう

HTTP vs WebSocket

HTTPはリクエスト/レスポンス型のプロトコルです。 クライアントがリクエストを送り、サーバーが応答を返します。サーバーからクライアントへ 自発的にデータを送ることはできません。

一方、WebSocketは一度接続を確立すると、 クライアントとサーバーの両方から自由にデータを送受信できる全二重通信が可能です。

【HTTP通信】
クライアント → リクエスト → サーバー
クライアント ← レスポンス ← サーバー
(毎回接続を張り直す / サーバーから送れない)

【WebSocket通信】
クライアント ←→ 双方向データ ←→ サーバー
(常時接続 / どちらからでも送信可能)

【ポーリング vs WebSocket】
ポーリング: 定期的にHTTPリクエストを送って新しいデータを確認
  → 無駄なリクエストが大量発生、遅延が大きい

WebSocket: 接続を維持し、データが発生したら即座に送信
  → リアルタイム性が高く、オーバーヘッドが小さい

ハンドシェイクプロセス

WebSocket接続はHTTPアップグレードリクエストから始まります。 最初にHTTPでハンドシェイクを行い、成功するとプロトコルがWebSocketに切り替わります。

// 1. クライアントからのアップグレードリクエスト
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

// 2. サーバーからのアップグレードレスポンス
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

// 3. ここからWebSocketフレームで双方向通信開始
// HTTPヘッダーのオーバーヘッドが不要になる

全二重通信(Full-Duplex)

WebSocketの最大の特徴は全二重通信です。 クライアントとサーバーが同時にデータを送受信できます。 これにより、リアルタイム性の高いアプリケーションを構築できます。

半二重通信(HTTP)

一度に一方向のみ通信可能。リクエストを送ったら、レスポンスが返るまで待つ必要がある。

全二重通信(WebSocket)

同時に双方向の通信が可能。サーバーはいつでもクライアントにデータをプッシュできる。

WebSocketのユースケース

WebSocketは以下のようなリアルタイム性が求められるアプリケーションで活躍します。

チャットアプリ

メッセージの即座な送受信。Slack、Discord、LINEなどが代表例。

オンラインゲーム

プレイヤー間のリアルタイム同期。位置情報やアクションの即時反映。

ライブ更新

株価、スポーツスコア、SNSフィードなどのリアルタイム更新。

共同編集

Google Docsのような複数人同時編集。変更の即時反映が必要。

ブラウザのWebSocket API

ブラウザにはネイティブWebSocket APIが組み込まれています。 ライブラリなしでWebSocket通信を実装できます。

// WebSocket接続の作成
const ws = new WebSocket("ws://localhost:3001");

// 接続が開いたとき
ws.addEventListener("open", () => {
  console.log("接続成功!");
  ws.send("こんにちは、サーバー!");
});

// メッセージを受信したとき
ws.addEventListener("message", (event) => {
  console.log("受信:", event.data);
});

// エラーが発生したとき
ws.addEventListener("error", (error) => {
  console.error("WebSocketエラー:", error);
});

// 接続が閉じたとき
ws.addEventListener("close", (event) => {
  console.log("接続終了:", event.code, event.reason);
});

// メッセージの送信
ws.send(JSON.stringify({ type: "chat", text: "Hello!" }));

// 接続を閉じる
ws.close(1000, "正常終了");

Node.jsでWebSocketサーバー

wsパッケージを使ってNode.jsでWebSocketサーバーを作成できます。

// npm install ws
import { WebSocketServer } from "ws";

const wss = new WebSocketServer({ port: 3001 });

wss.on("connection", (ws) => {
  console.log("クライアントが接続しました");

  // メッセージ受信
  ws.on("message", (data) => {
    const message = data.toString();
    console.log("受信:", message);

    // 全クライアントにブロードキャスト
    wss.clients.forEach((client) => {
      if (client.readyState === 1) { // OPEN状態
        client.send(message);
      }
    });
  });

  // 接続終了
  ws.on("close", () => {
    console.log("クライアントが切断しました");
  });

  // ウェルカムメッセージ
  ws.send("サーバーに接続しました!");
});

console.log("WebSocketサーバー起動: ws://localhost:3001");

まとめ

  • WebSocketはHTTPと異なり、常時接続の全二重通信を実現するプロトコル
  • HTTPアップグレードリクエストでハンドシェイクを行い接続を確立する
  • チャット、ゲーム、ライブ更新など、リアルタイム性が求められる場面で活躍
  • ブラウザにはネイティブWebSocket APIが組み込まれている
  • Node.jsではwsパッケージでWebSocketサーバーを簡単に構築できる