メインコンテンツにスキップ
バージョン: 4.x

ルーム

ルームとは、ソケットがjoinおよびleaveできる任意のチャネルです。クライアントのサブセットにイベントをブロードキャストするために使用できます。

Broadcasting to all clients in a roomBroadcasting to all clients in a room
情報

ルームはサーバー側のみの概念であることに注意してください(つまり、クライアントは参加したルームのリストにアクセスできません)。

参加と退出

joinを呼び出して、ソケットを特定のチャネルにサブスクライブできます。

io.on("connection", (socket) => {
socket.join("some room");
});

ブロードキャストまたは発行するときは、toまたはin(同じです)を使用します。

io.to("some room").emit("some event");

またはルームを除外します。

io.except("some room").emit("some event");

複数のルームに同時に発行することもできます。

io.to("room1").to("room2").to("room3").emit("some event");

その場合、和集合が実行されます。少なくとも1つのルームにいるすべてのソケットは、イベントを1回受信します(ソケットが2つ以上のルームにいる場合でも)。

特定のソケットからルームにブロードキャストすることもできます。

io.on("connection", (socket) => {
socket.to("some room").emit("some event");
});

その場合、ルーム内のすべてのソケット(送信者を除く)がイベントを受信します。

Broadcasting to all clients in a room excepting the senderBroadcasting to all clients in a room excepting the sender

チャネルを離れるには、joinと同じようにleaveを呼び出します。

使用例

  • 特定のユーザーの各デバイス/タブにデータをブロードキャストする
function computeUserIdFromHeaders(headers) {
// to be implemented
}

io.on("connection", async (socket) => {
const userId = await computeUserIdFromHeaders(socket.handshake.headers);

socket.join(userId);

// and then later
io.to(userId).emit("hi");
});
  • 特定のエンティティに関する通知を送信する
io.on("connection", async (socket) => {
const projects = await fetchProjects(socket);

projects.forEach(project => socket.join("project:" + project.id));

// and then later
io.to("project:4321").emit("project updated");
});

切断

切断すると、ソケットは自動的に参加していたすべてのチャネルをleaveし、こちらで特別なシャットダウンは必要ありません。

disconnectingイベントをリッスンすることで、ソケットが存在していたルームを取得できます。

io.on("connection", socket => {
socket.on("disconnecting", () => {
console.log(socket.rooms); // the Set contains at least the socket ID
});

socket.on("disconnect", () => {
// socket.rooms.size === 0
});
});

複数のSocket.IOサーバーを使用する場合

グローバルブロードキャストと同様に、ルームへのブロードキャストも複数のSocket.IOサーバーで機能します。

デフォルトのアダプターをRedisアダプターに置き換えるだけで済みます。詳細については、こちらを参照してください。

Broadcasting to all clients in a room with RedisBroadcasting to all clients in a room with Redis

実装の詳細

"ルーム"機能は、アダプターと呼ばれるもので実装されています。このアダプターは、次の役割を担うサーバー側のコンポーネントです。

  • ソケットインスタンスとルーム間の関係を格納する
  • すべて(またはクライアントのサブセット)にイベントをブロードキャストする

デフォルトのインメモリアダプターのコードは、こちらにあります。

基本的には、2つのES6 Mapで構成されています。

  • sids: Map<SocketId, Set<Room>>
  • rooms: Map<Room, Set<SocketId>>

socket.join("the-room")を呼び出すと、次のようになります。

  • sids Mapで、ソケットIDで識別されるSetに"the-room"を追加する
  • rooms Mapで、文字列"the-room"で識別されるSetにソケットIDを追加する

これらの2つのマップは、ブロードキャスト時に使用されます。

  • すべてのソケットへのブロードキャスト(io.emit())はsids Mapをループし、すべてのソケットにパケットを送信します。
  • 特定のルームへのブロードキャスト(io.to("room21").emit())はrooms Map内のSetをループし、一致するすべてのソケットにパケットを送信します。

これらのオブジェクトには、次の方法でアクセスできます。

// main namespace
const rooms = io.of("/").adapter.rooms;
const sids = io.of("/").adapter.sids;

// custom namespace
const rooms = io.of("/my-namespace").adapter.rooms;
const sids = io.of("/my-namespace").adapter.sids;

注記

  • これらのオブジェクトは直接変更することを意図していません。常にsocket.join(...)socket.leave(...)を使用する必要があります。
  • マルチサーバー設定では、roomsおよびsidsオブジェクトはSocket.IOサーバー間で共有されません(ルームは、あるサーバーにのみ「存在」し、別のサーバーには存在しない場合があります)。

ルームイベント

socket.io@3.1.0以降、基盤となるアダプターは次のイベントを発行します。

  • create-room (引数: ルーム)
  • delete-room (引数: ルーム)
  • join-room (引数: ルーム、ID)
  • leave-room (引数: ルーム、ID)

io.of("/").adapter.on("create-room", (room) => {
console.log(`room ${room} was created`);
});

io.of("/").adapter.on("join-room", (room, id) => {
console.log(`socket ${id} has joined room ${room}`);
});