WebSocket レッスン2
Socket.IO入門
イベント駆動のリアルタイム通信ライブラリを使いこなそう
なぜSocket.IOを使うのか?
ネイティブWebSocket APIはシンプルですが、実際のアプリケーション開発では 多くの課題があります。Socket.IOはそれらを解決してくれます。
自動再接続
接続が切れた場合に自動的に再接続を試みる。ネイティブWSにはこの機能がない。
イベントベース
カスタムイベント名でデータを送受信できる。メッセージの種類を簡単に区別できる。
フォールバック
WebSocketが使えない環境ではHTTPロングポーリングに自動的にフォールバックする。
ルーム・名前空間
グループ通信やチャネル分離の仕組みが組み込まれている。
サーバーのセットアップ
socket.ioパッケージをインストールして、 Express と組み合わせてサーバーを構築します。
// npm install express socket.io
import express from "express";
import { createServer } from "http";
import { Server } from "socket.io";
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log("ユーザー接続:", socket.id);
// クライアントからのイベントを受信
socket.on("chat:message", (data) => {
console.log("メッセージ:", data);
});
// 切断時
socket.on("disconnect", (reason) => {
console.log("ユーザー切断:", socket.id, reason);
});
});
httpServer.listen(3001, () => {
console.log("Socket.IOサーバー起動: http://localhost:3001");
});クライアントのセットアップ
socket.io-clientパッケージを使って、 ブラウザからSocket.IOサーバーに接続します。
// npm install socket.io-client
import { io } from "socket.io-client";
// サーバーに接続
const socket = io("http://localhost:3001", {
autoConnect: true, // 自動接続
reconnection: true, // 自動再接続
reconnectionAttempts: 5, // 再接続試行回数
reconnectionDelay: 1000, // 再接続間隔(ミリ秒)
});
// 接続成功
socket.on("connect", () => {
console.log("接続成功:", socket.id);
});
// 接続エラー
socket.on("connect_error", (error) => {
console.error("接続エラー:", error.message);
});
// 切断
socket.on("disconnect", (reason) => {
console.log("切断:", reason);
});emit / on でイベント通信
Socket.IOの通信はイベント駆動です。emitでイベントを送信し、onでイベントを受信します。
// ===== クライアント側 =====
// イベントを送信(文字列)
socket.emit("chat:message", "こんにちは!");
// イベントを送信(オブジェクト)
socket.emit("chat:message", {
user: "田中",
text: "こんにちは!",
timestamp: Date.now(),
});
// イベントを受信
socket.on("chat:message", (data) => {
console.log(`${data.user}: ${data.text}`);
});
// ===== サーバー側 =====
io.on("connection", (socket) => {
// 特定のクライアントからのイベント受信
socket.on("chat:message", (data) => {
console.log("受信:", data);
// 送信元を含む全員に送信
io.emit("chat:message", data);
});
});ブロードキャスト
メッセージの送信先にはいくつかのパターンがあります。 用途に応じて使い分けましょう。
io.on("connection", (socket) => {
// 1. 全員に送信(送信者を含む)
io.emit("notification", "全員へのお知らせ");
// 2. 送信者以外の全員に送信
socket.broadcast.emit("notification", "他の全員へ");
// 3. 送信者のみに送信
socket.emit("notification", "あなただけに");
// 4. 特定のソケットIDに送信
io.to(targetSocketId).emit("private", "個別メッセージ");
// 5. 複数の宛先に送信
io.to(socketId1).to(socketId2).emit("group", "グループメッセージ");
});Acknowledgments(確認応答)
Acknowledgmentを使うと、 イベントの送信後にサーバーからの応答を受け取ることができます。 HTTPのリクエスト/レスポンスに似た挙動を実現できます。
// ===== クライアント側 =====
// コールバックで応答を受け取る
socket.emit("chat:message", { text: "Hello!" }, (response) => {
if (response.status === "ok") {
console.log("メッセージ送信成功:", response.id);
} else {
console.error("送信失敗:", response.error);
}
});
// async/await スタイル(Socket.IO v4.6+)
const response = await socket.emitWithAck("chat:message", {
text: "Hello!",
});
console.log("応答:", response);
// ===== サーバー側 =====
socket.on("chat:message", (data, callback) => {
try {
// メッセージを保存
const id = saveMessage(data);
// 成功を応答
callback({ status: "ok", id });
} catch (error) {
// エラーを応答
callback({ status: "error", error: error.message });
}
});まとめ
- Socket.IOは自動再接続、フォールバック、ルーム機能などを提供するライブラリ
- サーバーはExpress + socket.io、クライアントはsocket.io-clientで構築
- emit/onのイベント駆動モデルで直感的にリアルタイム通信が書ける
- ブロードキャストのパターンを使い分けて適切な宛先にデータを送る
- Acknowledgmentで送信の成功/失敗を確認できる