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

Posted

技术标签:

【中文标题】Socket IO Rooms:获取特定房间的客户端列表【英文标题】:Socket IO Rooms: Get list of clients in specific room 【发布时间】:2013-08-08 06:06:02 【问题描述】:

我正在尝试显示特定房间中的客户列表。我只想显示他们的用户名,而不是他们的套接字 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 或任何东西。但是希望它返回昵称。

【问题讨论】:

【参考方案1】:

在 socket.IO 3.x 中

New to version 3.x is that connected is renamed to sockets and is now an ES6 Map on namespaces. 在房间的套接字上是一个 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 中

请参考以下答案: Get list of all clients in specific room。复制如下,稍作修改:

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')

【讨论】:

我需要 > 1.0 的东西,但是你清楚地表明这不适用于上面的 1.0,没有理由反对。有一个 +1 来平衡它:p。【参考方案2】:

不要深入socket/io对象,你可以使用简单而标准的方式:

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

更多详情DO READ

【讨论】:

如何使用 async 和 await ? 请注意,此解决方案不适用于 socket.IO v3 或更高版本。【参考方案3】:

只是一些事情。

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

    您的:

    console.log('User joined chat room 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);
);

为了帮助你更多,我需要查看你所有的代码,因为这没有给我上下文。

【讨论】:

“io.sockets.clients('chatroom1')”在 nodejs v1.0 及更高版本中工作吗? 您好,我在io.sockets.clients('roomname')中遇到错误,mysocket版本是2.2.0 虽然这是公认的答案,但它不适用于高于 socket.io 1.0 的版本。 这个方法不存在了 方法给出错误:客户端不是函数【参考方案4】:

对于 v4,我使用了这个方法 fetchSockets()

例子:

let roomUsers=await io.in(`room-id`).fetchSockets()

在此处查看文档: https://socket.io/docs/v3/migrating-from-3-x-to-4-0/#Additional-utility-methods

【讨论】:

【参考方案5】:

如果您使用 2.0,上述所有答案以及此处 socket.io get rooms which socket is currently in 或此处 Socket.IO - how do I get a list of connected sockets/clients? 的答案要么不正确要么不完整。

    在 2.0 中,io.sockets.managerio.sockets.clients 不再存在。

    不使用命名空间,以下3个参数都可以获取特定房间的sockets。

    socket.adapter.rooms;

    io.sockets.adapter.rooms;

    io.sockets.adapter.sids; // the socket.id array

    有了命名空间(我在这里使用了“cs”),io.sockets.adapter.rooms 会给出一个相当混乱的结果,而socket.adapter.rooms 给出的结果是正确的:

/* socket.adapter.rooms give: */


  "/cs#v561bgPlss6ELZIZAAAB": 
    "sockets": 
      "/cs#v561bgPlss6ELZIZAAAB": true
    ,
    "length": 1
  ,
  "a room xxx": "sockets": 
    "/cs#v561bgPlss6ELZIZAAAB": true
  ,
  "length": 1
  


/* io.sockets.adapter.rooms give: a sid without namespace*/


  "v561bgPlss6ELZIZAAAB": 
    "sockets": 
      "v561bgPlss6ELZIZAAAB": true
    , "length": 1
  

注意:默认房间是这样的:“Each Socket in Socket.IO is identified by a random, unguessable, unique identifier Socket#id. For your convenience, each socket automatically joins a room identified by this id。”

目前只尝试过内存适配器,没有尝试过redis-adapter。

【讨论】:

【参考方案6】:

对于socket.IO v3,这里有一个重大更改:

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

之前:

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

现在 (v3):

// all sockets in the "chat" namespace and in the "general" room
const ids = await io.of("/chat").in("general").allSockets();

Source

如果您对 socket.IO 不太熟悉,最好知道您可以编写 io 来代替 io.of("/chat") 来使用默认命名空间。

【讨论】:

这也适用于 Socket.IO v4。准确地说,上面的示例代码返回的是一组套接字 ID,而不是实际的 Socket 对象。 io.of('/').sockets 可用于获取连接到命名空间的 Socket 实例的 Map,因此 io.of('/').sockets.get(socketId) 获取与 id 匹配的 Socket 实例。【参考方案7】:

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' ]

【讨论】:

【参考方案8】:

对于大于 v1.0 的 Socket.io 和节点 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))

【讨论】:

【参考方案9】:

Socket.io v3 开始,rooms 现在是 Adapter 的受保护属性,因此您将无法通过 io.sockets.adapter.rooms 访问它。

改为使用:

const clientsInRoom = await io.in(roomName).allSockets()

OR 用于多个房间

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

【讨论】:

【参考方案10】:

对于 Socket v.4,正确的语法是:

const sockets = await io.in("room1").fetchSockets();

https://socket.io/docs/v4/server-api/#namespacefetchsockets

【讨论】:

【参考方案11】:

我刚刚将房间中的所有套接字都记录到控制台,你可以对它们做任何你喜欢的事情......

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)
        
    

【讨论】:

【参考方案12】:

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

io.sockets.adapter.rooms.get("chatroom1")

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

【讨论】:

【参考方案13】:

socket.io ^2.2.0

const socket = io(url)

socket.on('connection', client => 
  socket.of('/').in("some_room_name").clients((err, clients) => 
    console.log(clients) // an array of socket ids
  )
)

【讨论】:

我怎样才能使用 async 和 await 呢? 一个简单的答案是将整个事情包装在一个异步函数中并等待回调。这可能会有所帮助:***.com/questions/47035243/…【参考方案14】:

此解决方案适用于

socket.io:“3.0.4” socket.io-redis:“6.0.1”

先导入这些

const redis = require('socket.io-redis');
io.adapter(redis( host: 'localhost', port: 6379 ));

socket.on('create or join', function(room) 
    log('Received request to create or join room ' + room);

    //var clientsInRoom = io.sockets.adapter.rooms[room];
    
    mapObject = io.sockets.adapter.rooms // return Map Js Object
    clientsInRoom = new Set(mapObject.get(room))
  
    var numClients = clientsInRoom ? clientsInRoom.size : 0;
    log('Room ' + room + ' now has ' + numClients + ' client(s)');

https://socket.io/docs/v3/using-multiple-nodes/#The-Redis-adapter https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Map/get

【讨论】:

【参考方案15】:

由于我几乎没有找到关于如何在特定命名空间中获取房间的信息,所以在这里以防万一有人想知道:

io.of(namespaceName).adapter.rooms;

【讨论】:

【参考方案16】:

您可以将用户集合的数组对象创建为

var users = ;

然后在服务器端,您可以在连接时将其添加为新用户

socket.on('new-user', function (username) 
    users[username] = username;
);

在显示用户时,您可以循环“用户”对象

在客户端

var socket = io.connect();

socket.on('connect', function () 
    socket.emit('new-user', 'username');
);

【讨论】:

说真的,您要从客户端发送用户名而不是检查 cookie 和其他东西?是不是很容易伪造? 我建议使用带有中间件的 socket.handshake.query 进行身份验证,然后将该令牌/用户名存储为套接字属性以从服务器端引用,这样它就可以正常工作了。

以上是关于Socket IO Rooms:获取特定房间的客户端列表的主要内容,如果未能解决你的问题,请参考以下文章

向 Socket.io 中的其他房间发送消息

如何获取房间中的socket.io客户端数量?

Node.js 库“Socket.IO”中“房间”的安全性

Socket.IO API Socket

如何在 socket.io 1.0 中获取房间的客户列表

使用 socket.io 时如何获取房间内的客户端数量?