Socket.io中解析Map类型rooms数据,统计连接数最多的房间
Socket.io房间连接数统计:找出连接数最多的子房间
一、关于io.sockets.adapter.rooms的数据类型
io.sockets.adapter.rooms是ES6原生Map对象,它是一种键值对集合:键为房间标识(字符串类型的文档_id或guestRoom),值是存储该房间内所有Socket ID的Set集合。普通对象的遍历方法(比如Object.entries)无法直接读取Map的键值对,因为Map的存储结构和普通对象不同,所以你之前用Object.entries返回空数组是正常的。
二、正确读取Map并统计连接数的方法
你可以通过Map的原生API来遍历和处理数据,下面提供两种实用的实现方式:
方式1:转成数组后统计(直观易读)
// 1. 将Map转为包含[房间ID, Socket集合]的数组 const roomsEntries = Array.from(io.sockets.adapter.rooms.entries()); // 2. 过滤出目标子房间(排除guestRoom,保留文档_id命名的房间),并生成统计数据 const roomStats = roomsEntries .filter(([roomId]) => roomId !== 'guestRoom') // 根据你的规则调整过滤条件 .map(([roomId, socketSet]) => ({ roomId, connectionCount: socketSet.size // Set的size属性就是该房间的连接数 })); // 3. 找出连接数最多的房间 if (roomStats.length === 0) { console.log('没有符合条件的子房间'); } else { const topRoom = roomStats.reduce((prev, curr) => { return curr.connectionCount > prev.connectionCount ? curr : prev; }); console.log(`连接数最多的子房间:${topRoom.roomId},连接数:${topRoom.connectionCount}`); }
方式2:直接遍历Map(性能更优)
如果服务器房间数量较多,直接遍历Map可以避免数组转换的开销:
let maxConnectionCount = 0; let topRoomId = null; // 遍历Map的所有键值对 for (const [roomId, socketSet] of io.sockets.adapter.rooms) { // 跳过guestRoom本身,只统计子房间 if (roomId === 'guestRoom') continue; const currentCount = socketSet.size; // 更新最大连接数和对应房间ID if (currentCount > maxConnectionCount) { maxConnectionCount = currentCount; topRoomId = roomId; } } // 输出结果 if (topRoomId) { console.log(`连接数最多的子房间:${topRoomId},连接数:${maxConnectionCount}`); } else { console.log('未找到符合条件的子房间'); }
三、注意事项
- 如果你的文档_id有特定格式(比如MongoDB的24位十六进制ID),可以修改过滤条件,比如用正则匹配:
return /^[0-9a-fA-F]{24}$/.test(roomId),确保只统计目标子房间。 - Socket.io的
roomsMap中,每个Socket自身也会被视为一个以Socket ID命名的房间,如果你不需要统计这些房间,可以在过滤时排除:return roomId !== 'guestRoom' && !io.sockets.sockets.has(roomId)(判断房间ID是否对应某个Socket)。
内容的提问来源于stack exchange,提问作者Austin Howard
相关产品推荐
相关产品推荐

