Javascript Socket IO房间:获取特定房间中的客户端列表

Javascript Socket IO房间:获取特定房间中的客户端列表,javascript,node.js,socket.io,Javascript,Node.js,Socket.io,我正在尝试显示特定房间中的客户列表。我只想显示他们的用户名,而不是他们的套接字id 这就是我所处的位置: socket.set('nickname', "Earl"); socket.join('chatroom1'); console.log('User joined chat room 1); var roster = io.sockets.clients('chatroom1'); for ( i in roster ) { console.log('Username: ' +

我正在尝试显示特定房间中的客户列表。我只想显示他们的用户名,而不是他们的套接字id

这就是我所处的位置:

socket.set('nickname', "Earl");  
socket.join('chatroom1');
console.log('User joined chat room 1);

var roster = io.sockets.clients('chatroom1');
for ( i in roster )
{
   console.log('Username: ' + roster[i]);   
}
没有任何运气让它列出套接字ID或任何东西。但是,希望它返回昵称。

只是一些事情

  • 当您拥有
    socket
    时,您可以设置如下属性:
    socket.nickname='Earl'稍后使用save属性,例如在控制台日志中:
    
    console.log(socket.昵称)

  • 如果您的以下文件中缺少结束引号('):

    console.log('用户加入聊天室1)

  • 我不完全确定你的循环

  • 下面是修改后的代码,应该对您有所帮助,还要注意我下面使用的循环是异步的,这可能会影响您处理数据传输的方式

    socket.nickname = 'Earl';
    socket.join('chatroom1');
    
    console.log('User joined chat room 1');
        
    var roster = io.sockets.clients('chatroom1');
            
    roster.forEach(function(client) {
        console.log('Username: ' + client.nickname);
    });
    

    为了更好地帮助您,我需要查看您的所有代码,因为这不提供上下文。

    您可以创建用户集合的数组对象,如下所示:

    var users = {};
    
    然后在服务器端,您可以在连接时将其添加为新用户

    socket.on('new-user', function (username) {
        users[username] = username;
    });
    
    显示用户时,可以循环“users”对象

    在客户端

    var socket = io.connect();
    
    socket.on('connect', function () {
        socket.emit('new-user', 'username');
    });
    

    在socket.IO 3.x中

    房间上的套接字是一组ES6客户端ID

    //this is an ES6 Set of all client ids in the room
    const clients = io.sockets.adapter.rooms.get('Room Name');
    
    //to get the number of clients in this room
    const numClients = clients ? clients.size : 0;
    
    //to just emit the same event to all members of a room
    io.to('Room Name').emit('new event', 'Updates');
    
    for (const clientId of clients ) {
    
         //this is the socket of each client in the room.
         const clientSocket = io.sockets.sockets.get(clientId);
    
         //you can do whatever you need with this
         clientSocket.leave('Other Room')
    
    }
    
    在socket.IO 1.x到2.x之间

    请参考以下答案: . 复制了以下内容,并进行了一些修改:

    const clients = io.sockets.adapter.rooms['Room Name'].sockets;   
    
    //to get the number of clients in this room
    const numClients = clients ? Object.keys(clients).length : 0;
    
    //to just emit the same event to all members of a room
    io.to('Room Name').emit('new event', 'Updates');
    
    for (const clientId in clients ) {
    
         //this is the socket of each client in the room.
         const clientSocket = io.sockets.connected[clientId];
    
         //you can do whatever you need with this
         clientSocket.leave('Other Room')
    }
    

    如果使用2.0,以上所有答案以及此处或此处的答案都不正确或不完整

  • 在2.0中,
    io.sockets.manager
    io.sockets.clients
    不再存在
  • 如果不使用名称空间,以下3个参数都可以在特定房间中获取套接字

    socket.adapter.rooms

    io.sockets.adapter.rooms

    io.sockets.adapter.sids;//socket.id数组

  • 对于名称空间(我在这里使用了“cs”),
    io.sockets.adapter.rooms
    将给出一个非常混乱的结果,并且
    socket.adapter.rooms
    给出的结果是正确的:

  • 注意:默认房间为:”


    到目前为止,我只试过内存适配器,还没有试过redis适配器。

    不要深入到
    套接字/io
    对象中,您可以使用简单而标准的方法:

    io.in(room_name).clients((err , clients) => {
        // clients will be array of socket ids , currently available in given room
    });
    

    有关Socket.io大于v1.0和node v6.0+的更多详细信息,请使用以下代码:

    function getSockets(room) { // will return all sockets with room name
      return Object.entries(io.sockets.adapter.rooms[room] === undefined ?
      {} : io.sockets.adapter.rooms[room].sockets )
        .filter(([id, status]) => status) // get only status = true sockets 
        .map(([id]) => io.sockets.connected[id])
    }
    
    如果要向它们发射某些东西,请使用以下命令:

    getSockets('room name').forEach(socket => socket.emit('event name', data))
    

    我刚刚把一个房间里的所有插座都记录到控制台上,你可以用它们做任何你喜欢的事情

    const socketsInRoom = io.adapter.rooms[room_name];
    
        /*Collect all participants in room*/
        for(let participant in socketsInRoom){
            for(let socketId in socketsInRoom[participant]){
                console.log(socketId)
            }
        }
    

    socket.io^2.2.0

    const socket=io(url)
    socket.on('connection',client=>{
    socket.of(“/”).in(“某些房间名称”).clients((错误,clients)=>{
    console.log(clients)//套接字ID数组
    })
    })
    
    socket.io^2.0

    function getRoomClients(room) {
      return new Promise((resolve, reject) => {
        io.of('/').in(room).clients((error, clients) => {
          resolve(clients);
        });
      });
    }
    
    ...
    const clients = await getRoomClients('hello-world');
    console.log(clients);
    
    输出

    [ '9L47TWua75nkL_0qAAAA',
    'tVDBzLjhPRNdgkZdAAAB',
    'fHjm2kxKWjh0wUAKAAAC' ]
    

    对于
    socket.IO v3
    这里有一个突破性的变化:

    Namespace.clients()重命名为Namespace.allSockets(),现在返回一个承诺

    之前:

    // all sockets in the "chat" namespace and in the "general" room
    io.of("/chat").in("general").clients((error, clients) => {
      console.log(clients); // => [Anw2LatarvGVVXEIAAAD]
    });
    
    现在(v3):


    如果您对socket.IO不太熟悉,最好知道,您可以编写
    IO
    来使用默认名称空间,而不是(“/chat”)
    IO.of(“/chat”)

    socket.IO v3
    rooms
    现在是
    Adapter
    的受保护属性,因此您将无法通过
    io.sockets.Adapter.rooms
    访问它

    而是使用:

    const clientsInRoom = await io.in(roomName).allSockets()
    
    还是多个房间

    const clientsInRooms = await io.sockets.adapter.sockets(new Set([roomName, roomName2]))
    

    您可以在io对象上使用适配器方法,如

    io.sockets.adapter.rooms.get("chatroom1")
    
    这将返回特定房间中已连接客户端的列表。 io.sockets.adapter.rooms这是连接到房间的所有客户端的映射,房间名称作为键,连接的客户端是房间键的值。地图功能适用。

    此解决方案适用于

    • socket.io:“3.0.4”
    • socket.io-redis:“6.0.1”
    先导入这些
    const redis=require('socket.io redis');
    
    适配器(redis({host:'localhost',端口:6379}))由于我对如何在特定名称空间中获取文件室几乎没有发现什么,所以这里有一个例子,以防有人想知道:


    io.of(namespaceName).adapter.rooms

    io.sockets.clients('chatroom1')在nodejs v1.0及以上版本中有效吗?您好,我在io.sockets.clients('roomname')中遇到一个错误,mysocket版本是2.2.0虽然这是公认的答案,但它不适用于大于socket.io 1.0的版本。此方法不存在任何其他方法给出错误:客户端不是函数,你要从客户端发送用户名而不是检查cookies之类的东西?这不是很容易伪造吗?我建议使用socket.handshake.query和中间件进行身份验证,然后将该令牌/用户名存储为socket属性,从服务器端引用,这样它就可以正常工作。我需要大于1.0的东西,但您明确指出这在上面的1.0上不起作用,没有理由否决。有一个+1来平衡它:p.@TheZ你能用这些修改来编辑上面的答案吗?我希望看到这些更改反映在答案中。更新了答案,使其也包含socket.IO 3.x的信息。我如何使用async和Wait进行此操作?请注意,此解决方案不适用于socket.IO v3或更高版本。我如何使用async和Wait进行此操作?一个简单的答案是将整个内容包装在一个异步函数中,并等待响应回调。这可能会有所帮助:这也适用于Socket.iov4。准确地说,上面的示例代码返回一组套接字ID,而不是实际的套接字对象
    io.of(“/”).sockets
    可用于获取连接到命名空间的套接字实例的映射,以便
    io.of(“/”).sockets.get(socketId)
    获取与id匹配的套接字实例。
    const clientsInRooms = await io.sockets.adapter.sockets(new Set([roomName, roomName2]))
    
    io.sockets.adapter.rooms.get("chatroom1")