如何在socket.io的Node.js服务器上列出房间

42
在探讨如何创建Socket.IO多播组的进程中,我发现创建房间是实现所需功能的好方法。
然而,若能无需额外数据结构即可了解所有房间信息会更好。
是否可以通过服务器套接字从服务器获取所有房间的列表?

抱歉完全错过了这个答案,但希望我下面的回答能帮到你。 - Alfred
17个回答

57

简短回答:

io.sockets.adapter.rooms

我分析了 io:

我得到了以下输出:

{ server: 
   { stack: 
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ],
     connections: 3,
     allowHalfOpen: true,
     watcher: { host: [Circular], callback: [Function] },
     _events: 
      { request: [Function],
        connection: [Function: connectionListener],
        listening: [Object],
        upgrade: [Object] },
     httpAllowHalfOpen: false,
     cache: {},
     settings: { home: '/', env: 'development', hints: true },
     redirects: {},
     isCallbacks: {},
     _locals: { settings: [Object], app: [Circular] },
     dynamicViewHelpers: {},
     errorHandlers: [],
     route: '/',
     routes: 
      { app: [Circular],
        routes: [Object],
        params: {},
        _params: [],
        middleware: [Function] },
     router: [Getter],
     __usedRouter: true,
     type: 'tcp4',
     fd: 7 },
  namespaces: 
   { '': 
      { manager: [Circular],
        name: '',
        sockets: [Object],
        auth: false,
        flags: [Object],
        _events: [Object] } },
  sockets: 
   { manager: [Circular],
     name: '',
     sockets: { '210837319844898486': [Object] },
     auth: false,
     flags: { endpoint: '', exceptions: [] },
     _events: { connection: [Function] } },
  settings: 
   { origins: '*:*',
     log: true,
     store: 
      { options: undefined,
        clients: [Object],
        manager: [Circular] },
     logger: { colors: true, level: 1 },
     heartbeats: true,
     resource: '/socket.io',
     transports: 
      [ 'websocket',
        'htmlfile',
        'xhr-polling',
        'jsonp-polling' ],
     authorization: [Function],
     'log level': 1,
     'close timeout': 25,
     'heartbeat timeout': 15,
     'heartbeat interval': 20,
     'polling duration': 20,
     'flash policy server': true,
     'flash policy port': 843,
     'destroy upgrade': true,
     'browser client': true,
     'browser client minification': false,
     'browser client etag': false,
     'browser client handler': false,
     'client store expiration': 15 },
  handshaken: 
   { '210837319844898486': 
      { headers: [Object],
        address: [Object],
        time: 'Mon Jul 18 2011 00:53:27 GMT+0200 (CEST)',
        xdomain: false,
        secure: undefined,
        PHPSESSID: '7qo6cht3q0rskhfes4eesb2d05' } },
  connected: { '210837319844898486': true },
  open: { '210837319844898486': true },
  closed: {},
  closedA: [],
  rooms: 
   { '': [ '210837319844898486' ],
     '/public-alfred': [ '210837319844898486' ] },
  roomClients: { '210837319844898486': [ '': true, '/public-alfred': true ] },
  oldListeners: [ [Function] ],
  _events: 
   { 'set:origins': [Function],
     'set:flash policy port': [Function],
     'set:transports': [Function] } }

在单个客户端加入房间"public-alfred"之后,io.sockets.adapter.rooms包含了以下内容:

 { '': [ '210837319844898486' ],
         '/public-alfred': [ '210837319844898486' ] }

6
甚至更简单的是,io.rooms的作用与io.sockets.manager是循环引用的。它们会给你相同的结果,只是io.rooms更为简洁。 - ADAM
2
我认为这个无法与socket.io的1.0版本兼容。或许?io.nsps['/'].adapter.rooms - Arnaldo Capo
2
Alfred,我已经编辑了答案,适用于两个API版本,因为还有像我一样使用9.x版本的潜在读者 :) - Marwen Trabelsi
3
现在简单的 socket.rooms 就能解决问题了.. 进步真是令人喜爱 ;) - Dmitry Matveev
4
@Alfred,我正在使用1.4.x版本。如何获取io.sockets.adapters.rooms中每个房间的房间名称?当我创建并加入一个房间时,我会指定它的名称,例如 socket.join('someRoom'),但是当我使用io.sockets.adapters.rooms时,我得到的是一个类似 /#4Ps4Ql-bx2R3qFH6AAAC 的引用。我该如何获取相应的房间名? - Sajib Acharya
显示剩余2条评论

20

就像大家所说的,在新版本的socket.io(1.x)中,房间可以在以下位置找到:

    io.sockets.adapter.rooms

这将返回类似于以下内容:

{ 
    'qNADgg3CCxESDLm5AAAA': [ 'qNADgg3CCxESDLm5AAAA': true ],
    'myRoom': [ 'qNADgg3CCxESDLm5AAAA': true,
                '0rCX3v4pufWvQ6uwAAAB': true,
                'iH0wJHGh-qKPRd2RAAAC': true ],  
    '0rCX3v4pufWvQ6uwAAAB': [ '0rCX3v4pufWvQ6uwAAAB': true ],  
    'iH0wJHGh-qKPRd2RAAAC': [ 'iH0wJHGh-qKPRd2RAAAC': true ] 
}

我想要获取的唯一房间是“myRoom”,因此我编写了以下函数:

function findRooms() {
    var availableRooms = [];
    var rooms = io.sockets.adapter.rooms;
    if (rooms) {
        for (var room in rooms) {
            if (!rooms[room].hasOwnProperty(room)) {
                availableRooms.push(room);
            }
        }
    }
    return availableRooms;
}

这对我有点困惑,希望这可以帮助你!


你的 findRooms() 函数一直返回所有房间,因为该数组中的所有项都具有 room 属性。我使用的是 socket.io v1.4.5 版本。 - Pherrymason

17
在新版本的socket.io (1.x)中,io.sockets.manager.rooms会导致错误。你应该使用io.sockets.adapter.rooms代替。

@slier:这是正确的,只有第一个对象是默认房间 - 它看起来像一个随机字符串 - - Marwen Trabelsi

6
在socketIO 2.2.0版本中,
  • io.sockets.manager已不再存在。

您可以使用以下3种方法获取特定房间中的所有套接字。

socket.adapter.rooms;
io.sockets.adapter.rooms
io.sockets.adapter.sids

如果您正在使用命名空间,则应使用socket.adapter.rooms来获取房间列表。

{ '/userSocket#oXorUiql1GF68dbTAAAB':
   Room {
     sockets: { '/userSocket#oXorUiql1GF68dbTAAAB': true },
     length: 1 
     },
  roomOneName:
   Room {
     sockets: { '/userSocket#oXorUiql1GF68dbTAAAB': true },
     length: 1 
     },
  roomTwoName:
   Room {
     sockets: { '/userSocket#oXorUiql1GF68dbTAAAB': true },
     length: 1 
   } 
}

3

如果您正在使用socket.io 2.1.0,并遇到以下情况。

在2.1.0中,服务器中的所有房间都位于变量io.sockets.adapter.rooms中。

//Use Example//

sockets.on('getRooms', function() {
    sockets.emit('rooms', io.sockets.adapter.rooms);
});

您将获得以下结果。

{ xqfGuWYkKzT9hGgGAAAB: 房间 { sockets: { xqfGuWYkKzT9hGgGAAAB: true }, 长度: 1 }, '0Ak9nTjme7bLsD8NAAAC': 房间 { sockets: { '0Ak9nTjme7bLsD8NAAAC': true }, 长度: 1 } }

注意:本文中的“Room”是指“房间”,仅为翻译。请根据上下文确定术语含义。

3
Object.keys(io.sockets.adapter.rooms)

使用此方法获取所有房间。

2

如果io.sockets.adapterundefined..

我正在使用 socket.io 1.7.1 (服务器端)

在这个版本的socket.io中,似乎io.of("......").sockets.adapterundefined。所以我使用了io.adapter.rooms代替,并且它可以正常工作。


io.sockets.adapter.rooms 在 Socket.IO 1.7.3 中可用。 - calbertts

2
根据 Socket.io-v3.x 的文档,要获取所有当前创建的房间,只需简单地执行socket.rooms
io.on('connection', socket => {

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

并且它返回如下结果。
Set(2) {
  '_y_xQeeF6PpFiPQqAAFC',
  '6113cb71359644408895afcf6112df3c76981e3f88bc5c08'
} 

1

我能够在一个打开的连接上使用socket._events找到它们。

io.sockets.on('connection', function(socket){
  socket.on('ping', function(data){
    console.log(socket._events);
  });
});

输出:

{
  ping: [Function],
  disconnect: [Function]
}

1
我相信楼主问的是如何找房间,这应该是事件。在某些情况下仍然有帮助,但与这个问题无关。 - Chance Chapman

1

在v4中,可以按照以下方式进行:

Array.from(io.adapter.rooms.entries())

它将返回一个数组,其中包含键(roomIds)和值(socketIds),与Object.entries()相同的结构:
[
  [roomId],[Set(2) {"socketId1","socketId2"}],
  [roomId2], [Set(3) {"socketId3","socketId4","socketId5"}],
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接