このレッスンのロックを解除するには、まず「WebSocketプロトコルとHTTPの違いの理解」を完了してください。前のレッスンに戻る

はじめに

WebSocketは、単一のTCPソケット上でクライアントとサーバー間のフルデュプレックスで永続的な接続を可能にするプロトコルです。クライアントがリクエストしてサーバーが応答する通常のHTTPとは異なり、WebSocket接続は開いたまま維持され、両側がいつでもメッセージを送信できます。このため、チャットアプリ、ライブダッシュボード、マルチプレイヤーゲーム、リアルタイム更新を必要とするあらゆる機能に最適です。

このレッスンでは、最小限のWebSocket構成を構築します:Node.jsの人気ライブラリ`ws`を使ったサーバーと、それに接続してメッセージを交換するブラウザクライアントです。フレームワークも、データベースも不要 — 生のプロトコルのみを使い、その裏側で何が起きているかを理解します。

プロジェクトのセットアップ

プロジェクト用の新しいフォルダを作成し、初期化します。Node.js(バージョン18以降でOK)がインストールされている必要があります。

bash
mkdir ws-demo
cd ws-demo
npm init -y
npm install ws

`ws`パッケージは、Node.js用の高速で広く使われているWebSocket実装です。`npm install`の後、`node_modules`フォルダと`ws`を依存関係として記載した`package.json`が作成されます。

サーバーの作成

`server.js`というファイルを作成します。サーバーは3つのことを行います:ライブラリをインポートし、ポートにバインドされたWebSocketサーバーを作成し、接続時と受信メッセージ時の動作を定義します。

javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('A client connected');
ws.on('message', (data) => {
const text = data.toString();
console.log('Received:', text);
ws.send(`Server echo: ${text}`);
});
ws.send('Welcome to the WebSocket server!');
});
console.log('WebSocket server is listening on ws://localhost:8080');

`connection`イベントは、接続するクライアントごとに一度発生します。コールバックは、その個別クライアントのソケットを表す`ws`オブジェクトを受け取ります。コールバック内で`message`リスナーをアタッチします。メッセージが届くと、`data`はデフォルトでBufferなので、`toString()`でプレーンテキストに変換します。次にサーバーはメッセージを`Server echo:`をプレフィックスとして付加してエコーバックします。

`node server.js`でサーバーを実行します。「listening」というログ行が表示され、クライアントが接続するまで何も起こりません。

接続フローの図 — クライアントがCONNECTを送信し、サーバーが承認し、両者が単一のソケット上でMESSAGEを送り合う

ブラウザクライアントの作成

`index.html`というファイルを作成します。ブラウザは組み込みの`WebSocket`グローバルを使ってWebSocket接続を開くことができます — クライアント側にライブラリは不要です。

markup
<!DOCTYPE html>
<html>
<head><title>WebSocket Demo</title></head>
<body>
<h1>WebSocket Demo</h1>
<input id="msg" placeholder="Type a message" />
<button id="send">Send</button>
<ul id="log"></ul>
<script>
const log = document.getElementById('log');
const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener('open', () => {
log.innerHTML += '<li>Connected to server</li>';
});
ws.addEventListener('message', (event) => {
log.innerHTML += '<li>From server: ' + event.data + '</li>';
});
document.getElementById('send').addEventListener('click', () => {
const input = document.getElementById('msg');
ws.send(input.value);
input.value = '';
});
</script>
</body>
</html>

`open`イベントは、ハンドシェイクが完了したときに発生します。その後、`ws.send('text')`で文字列メッセージをサーバーに送信します。サーバーからのエコー応答は`message`イベントとして届き、`event.data`はサーバーが送信した文字列です。

エンドツーエンドのテスト

`node server.js`でサーバーを起動します。次にブラウザで`index.html`を開きます(ダブルクリックするか、`npx serve`などのツールを使用できます)。ターミナルには、ページが読み込まれた瞬間に「A client connected」が表示されるはずです。入力ボックスに何か入力してSendをクリックします。ブラウザのログにはメッセージが`Server echo:`プレフィックス付きで表示され、ターミナルにはサーバーが受信した各メッセージがログされます。

よくある間違い

サーバー側で`data.toString()`を忘れると、クライアントが送信した読み取り可能な文字列ではなく生のBufferオブジェクトが得られます。ブラウザのURLで`ws://`プロトコルプレフィックスを忘れると、`WebSocket`コンストラクタはスキームを含む完全なURLを必要とするため、構文エラーがスローされます。サーバーが実行されていない場合、ブラウザの`open`イベントは決して発生せず、ログエントリは表示されません — 何もないときは常にターミナルを最初に確認してください。

まとめ

これで動作するWebSocketエコーサーバーとブラウザクライアントが揃いました。サーバーは`ws`を使ってポート8080でリッスンし、接続を受け入れ、受信したメッセージをエコーバックします。クライアントは`new WebSocket('ws://localhost:8080')`で接続を開き、`send`と`message`イベントを使って通信します。このパターン — 1台のサーバー、多くの接続されたクライアント、双方向メッセージ — は、すべてのリアルタイム機能が構築される基盤です。

レッスンの練習

レッスンのチェックポイント

学んだ内容を復習し、回答へのフィードバックを受けましょう。

0/1
回答済み · 0/1