You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在最新版Socket.io中获取房间内的所有套接字

获取Socket.io最新版本中房间内的所有套接字

我完全懂你的烦恼——在Socket.io 1.0之前,io.sockets.clients('room')确实是快速获取指定房间内所有客户端套接字的好办法,但这个API早就被官方移除了,降级版本显然不是长久之计。下面我给你几个适配最新版本(包括3.x、4.x)的可靠解决方案:

方法一:利用Socket.io内置的适配器获取

Socket.io的默认内存适配器(以及Redis等集群适配器)会自动维护所有房间的客户端信息,你可以通过sockets.adapter.rooms来访问:

// 获取目标房间的套接字ID集合
const roomSocketIds = io.sockets.adapter.rooms.get('room');

if (roomSocketIds) {
  // 遍历每个套接字ID,获取对应的套接字实例
  roomSocketIds.forEach(socketId => {
    const targetSocket = io.sockets.sockets.get(socketId);
    // 这里可以对套接字进行操作,比如发送消息
    targetSocket.emit('room-notice', '这是发给房间内你的专属消息');
  });
}

注意:如果你的项目用了集群模式或者Redis适配器,这个方法依然有效,因为适配器会自动同步跨进程的房间数据。

方法二:自定义维护房间客户端列表

如果需要更灵活的控制(比如要存储客户端的用户ID、昵称等额外信息),可以在客户端加入/离开房间时手动维护一个映射表:

// 初始化一个Map,键是房间名,值是该房间内的套接字集合
const roomClientMap = new Map();

io.on('connection', (socket) => {
  // 监听客户端加入房间的事件
  socket.on('join-room', (roomName) => {
    socket.join(roomName);
    // 若房间不存在则创建新的集合
    if (!roomClientMap.has(roomName)) {
      roomClientMap.set(roomName, new Set());
    }
    roomClientMap.get(roomName).add(socket);
  });

  // 监听客户端离开房间的事件
  socket.on('leave-room', (roomName) => {
    socket.leave(roomName);
    if (roomClientMap.has(roomName)) {
      roomClientMap.get(roomName).delete(socket);
      // 房间为空时清理条目,节省内存
      if (roomClientMap.get(roomName).size === 0) {
        roomClientMap.delete(roomName);
      }
    }
  });

  // 客户端断开连接时,清理其加入的所有房间
  socket.on('disconnect', () => {
    roomClientMap.forEach((clients, room) => {
      clients.delete(socket);
      if (clients.size === 0) {
        roomClientMap.delete(room);
      }
    });
  });

  // 示例:获取指定房间的所有客户端ID
  socket.on('request-room-clients', (roomName) => {
    const clients = roomClientMap.get(roomName) || new Set();
    const clientIds = Array.from(clients).map(s => s.id);
    socket.emit('room-clients', clientIds);
  });
});

针对Socket.io 1.x版本的兼容方案

如果你用的是1.x版本(介于1.0到2.0之间),adapter.rooms的结构是普通对象而非Map,代码可以调整为:

const roomSockets = io.sockets.adapter.rooms['room'];
if (roomSockets) {
  Object.keys(roomSockets).forEach(socketId => {
    const targetSocket = io.sockets.connected[socketId];
    // 执行你的操作
  });
}

这些方案都不需要降级Socket.io版本,完全适配最新的官方规范,可以放心使用。

内容的提问来源于stack exchange,提问作者teamyates

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:48:33