35

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

4

16 回答 16

69

在 socket.IO 3.x 中

3.x 版本的新功能是 connected 被重命名为 sockets,现在是命名空间上的 ES6 Map。在房间套接字上是一组 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')
}
于 2014-07-30T04:47:37.627 回答
22

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

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

有关更多详细信息,请阅读

于 2018-05-10T10:20:43.107 回答
18

只是几件事。

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

  2. 您在以下内容中缺少结束引号 ('):

    console.log('User joined chat room 1);

  3. 我不完全确定你的循环。

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

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);
});

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

于 2013-08-07T06:59:07.777 回答
7

对于 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

于 2021-07-30T04:30:49.070 回答
5

上面的所有答案和这里的一个socket.io 获取当前套接字所在的房间或这里Socket.IO - 如何获取已连接套接字/客户端的列表?如果您使用 2.0,则不正确或不完整。

  1. 在 2.0 中,io.sockets.manager不再io.sockets.clients存在。
  2. 在不使用命名空间的情况下,以下 3 个参数都可以获取特定房间中的套接字。

    socket.adapter.rooms;

    io.sockets.adapter.rooms;

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

  3. 使用命名空间(我在这里使用了“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
  }
}

注意:默认房间是这样的:“ Socket.IO 中的每个 Socket 都由一个随机的、不可猜测的、唯一的标识符 Socket#id 标识。为了您的方便,每个套接字都会自动加入一个由这个 id 标识的房间。”

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

于 2017-07-04T10:48:00.190 回答
3

因为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();

来源

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

于 2020-12-10T19:20:51.237 回答
2

套接字.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' ]
于 2020-06-01T14:10:13.090 回答
1

对于大于 v1.0 和节点 v6.0+ 的 Socket.io,请使用以下代码:

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))
于 2018-05-26T05:29:47.267 回答
1

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]))
于 2020-12-17T10:12:16.527 回答
1

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

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

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

于 2021-11-03T13:08:43.823 回答
0

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

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)
        }
    }
于 2018-11-23T17:02:42.797 回答
0

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
  })
})
于 2019-06-22T20:46:08.843 回答
0

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

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

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

于 2021-01-01T07:09:54.000 回答
0

此解决方案适用于

  • 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/得到

于 2021-01-05T11:53:34.870 回答
0

由于我几乎没有找到关于如何将房间放入特定命名空间的信息,因此以防万一有人想知道:

io.of(namespaceName).adapter.rooms;

于 2021-05-07T04:12:35.090 回答
-3

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

var users = {};

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

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

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

在客户端

var socket = io.connect();

socket.on('connect', function () {
    socket.emit('new-user', 'username');
});
于 2013-08-07T07:58:00.547 回答