はじめに
リアルタイム通信が必要なWebアプリケーションを開発する際、Socket.IOは非常に便利なライブラリです。本記事では、Node.jsサーバーでSocket.IOを使うメリットや主な機能、ユースケース、そして実際のプロジェクト(SignalServer)を例にした実装方法・コード例を紹介します。
Socket.IOとは?
Socket.IOは、WebSocketをベースにしたリアルタイム通信ライブラリです。クライアント(ブラウザなど)とサーバー間で双方向通信を簡単に実現できます。WebSocketだけでなく、HTTPロングポーリングなども自動でフォールバック対応してくれるため、幅広い環境で安定して動作します。
主な特徴
- リアルタイム双方向通信
- クライアントとサーバー間で即時にデータを送受信できます。
- 自動リコネクト
- 通信が切断されても自動で再接続を試みます。
- ルーム・ネームスペース機能
- 特定のグループ(ルーム)や用途ごと(ネームスペース)に通信を分離できます。
- イベントベース通信
- 任意のイベント名でデータをやり取りでき、柔軟な設計が可能です。
- 多様なトランスポート対応
- WebSocketが使えない場合は自動でHTTPロングポーリング等に切り替えます。
ユースケース
Socket.IOはさまざまなリアルタイム機能を必要とするアプリケーションで活用されています。主な例は以下の通りです。
-
チャットアプリ
1対1やグループチャット、サポートチャットなど。 -
オンラインゲーム
プレイヤー間のリアルタイム同期、スコア共有、対戦型ゲームの状態管理。 -
リアルタイム通知
SNSやECサイトでの新着通知、システムアラート、プッシュ通知。 -
共同編集ツール
Google Docsのような複数人同時編集、ホワイトボードアプリ。 -
IoTデバイスとの通信
センサーやデバイスの状態をリアルタイムで監視・制御。 -
ライブ配信・ストリーミング
コメントのリアルタイム表示、視聴者数の即時反映。 -
位置情報共有アプリ
タクシー配車やフードデリバリーのリアルタイム位置追跡。 -
株価・為替レート表示
金融情報のリアルタイム更新。 -
スポーツ中継のスコア速報
試合経過やスコアの即時配信。 -
カスタマーサポートシステム
オペレーターとユーザーのリアルタイムチャットや画面共有。
サンプル実装(SignalServerプロジェクトより)
1. サーバー側(Node.js)
基本セットアップ
const http = require("http");
const { Server: IOServer } = require("socket.io");
const httpServer = http.createServer();
const io = new IOServer(httpServer, {
cors: {
origin: ["https://example.com"], // 許可するオリジン
methods: ["GET", "POST", "OPTIONS"],
credentials: true,
},
transports: ["websocket", "polling"],
});
httpServer.listen(3000, () => {
console.log("サーバー起動: http://localhost:3000");
});
認証付き接続
io.use((socket, next) => {
if (socket.handshake?.query?.authKey === "your_auth_key") {
socket.user = socket.id;
return next();
}
return next(new Error("Invalid key"));
});
ルーム作成・参加・退出
io.on("connection", (socket) => {
// ルーム作成・参加
socket.on("createRoom", async (data = {}) => {
const roomID = data.roomId;
if (!roomID) return;
socket.join(roomID);
// ルーム内ユーザー一覧を返す
const roomSockets = await io.in(roomID).fetchSockets();
const connectedUsers = roomSockets.map((s) => s.id);
io.to(socket.user).emit("joinedUsers", { users: connectedUsers });
});
// ルーム退出
socket.on("leaveRoom", (data = {}) => {
const roomID = data.roomId;
socket.leave(socket.id);
socket.to(roomID).emit("leaveRoom", {
roomId: roomID,
userId: socket.id,
});
});
});
WebRTCシグナリング(通話・ICE Candidate)
io.on("connection", (socket) => {
// 通話開始
socket.on("makeCall", (data = {}) => {
const roomID = data.roomId;
if (!roomID) return;
socket.to(roomID).emit("newCall", {
callerId: socket.user,
sdpOffer: data.sdpOffer,
});
});
// 通話応答
socket.on("answerCall", (data = {}) => {
const roomID = data.roomId;
if (!roomID) return;
socket.to(roomID).emit("callAnswered", {
callee: socket.user,
sdpAnswer: data.sdpAnswer,
});
});
// ICE Candidate
socket.on("IceCandidate", (data = {}) => {
const roomID = data.roomId;
if (!roomID) return;
socket.to(roomID).emit("IceCandidate", {
sender: socket.user,
iceCandidate: data.iceCandidate,
});
});
});
任意データ送信
io.on("connection", (socket) => {
socket.on("sendData", (data = {}) => {
const roomID = data.roomId;
if (!roomID) return;
socket.to(roomID).emit("receivedData", { data: data.data });
});
});
2. クライアント側
<script src="/socket.io/socket.io.js"></script>
<script>
// サーバーへ接続(認証キー付き)
const socket = io({
query: { authKey: "your_auth_key" }
});
// ルーム作成
socket.emit('createRoom', { roomId: 'room1' });
// ルーム内ユーザー一覧受信
socket.on('joinedUsers', function(data) {
console.log('ルーム内ユーザー:', data.users);
});
// 通話開始
socket.emit('makeCall', { roomId: 'room1', sdpOffer: '...' });
// 通話応答
socket.emit('answerCall', { roomId: 'room1', sdpAnswer: '...' });
// ICE Candidate送信
socket.emit('IceCandidate', { roomId: 'room1', iceCandidate: '...' });
// 任意データ送信
socket.emit('sendData', { roomId: 'room1', data: 'Hello!' });
// データ受信
socket.on('receivedData', function(data) {
console.log('受信データ:', data.data);
});
</script>
まとめ
Socket.IOを使うことで、Node.jsサーバーとクライアント間のリアルタイム通信が簡単に実装できます。SignalServerのようなプロジェクトでも、チャットやWebRTCシグナリング、通知、データ共有など様々な用途に活用できます。
Socket.IO公式サイト
Socket.IOドキュメント
Socket.IO GitHub
