0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.jsサーバーで使うSocket.IO入門 〜特徴・ユースケース・実装例(SignalServerベース)

0
Posted at

はじめに

リアルタイム通信が必要な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)
基本セットアップ

server.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");
});

認証付き接続

server.js
io.use((socket, next) => {
  if (socket.handshake?.query?.authKey === "your_auth_key") {
    socket.user = socket.id;
    return next();
  }
  return next(new Error("Invalid key"));
});

ルーム作成・参加・退出

server.js
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)

server.js
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,
    });
  });
});

任意データ送信

server.js
io.on("connection", (socket) => {
  socket.on("sendData", (data = {}) => {
    const roomID = data.roomId;
    if (!roomID) return;
    socket.to(roomID).emit("receivedData", { data: data.data });
  });
});

2. クライアント側

index.vue
<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>

結果
image.png

まとめ

Socket.IOを使うことで、Node.jsサーバーとクライアント間のリアルタイム通信が簡単に実装できます。SignalServerのようなプロジェクトでも、チャットやWebRTCシグナリング、通知、データ共有など様々な用途に活用できます。
Socket.IO公式サイト
Socket.IOドキュメント
Socket.IO GitHub

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?