Socket.IO - 如何获取连接的套接字/客户端列表?

And*_*Hin 144 node.js socket.io

我正在尝试获取当前连接的所有套接字/客户端的列表.

io.sockets 遗憾的是,它没有返回数组.

我知道我可以使用数组保留自己的列表,但不要认为这是一个最佳解决方案有两个原因:

  1. 冗余.Socket.IO已经保留了此列表的副本.

  2. Socket.IO提供了为客户端设置任意字段值的方法(即:),socket.set('nickname', 'superman')所以如果我要维护自己的列表,我需要跟上这些变化.

救命?

3rd*_*den 163

在Socket.IO 0.7中,您clients在命名空间上有一个方法,这将返回所有连接套接字的数组.

没有命名空间的API:

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`
Run Code Online (Sandbox Code Playgroud)

对于命名空间

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`
Run Code Online (Sandbox Code Playgroud)

希望这有助于未来的人

注意:此解决方案适用于1.0之前的版本

  • 他们几乎丢掉了1.0中的所有内容,因为它是完全重写的.但由于1.0已经多年没有发布.在1.0中,您必须使用命名空间的`connected`对象. (7认同)
  • @ 3rdEden,使用命名空间的连接对象的语法是什么?`var clients = io.sockets.connected();`显然不起作用.谢谢 (6认同)
  • 从1.x及以上:http://stackoverflow.com/questions/9352549/getting-how-many-people-are-in-a-chat-room-in-socket-io#24425207 (5认同)
  • 我认为他们已经放弃了1.0中的客户端方法......只是暂时检查出来... (3认同)

nha*_*nha 97

Socket.io 1.4

Object.keys(io.sockets.sockets); 为您提供所有连接的套接字.

Socket.io 1.0 从socket.io 1.0开始,实际接受的答案不再有效.所以我做了一个小函数,我用它作为临时修复:

function findClientsSocket(roomId, namespace) {
    var res = []
    // the default namespace is "/"
    , ns = io.of(namespace ||"/");

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                var index = ns.connected[id].rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}
Run Code Online (Sandbox Code Playgroud)

Api for No namespace变为

// var clients = io.sockets.clients();
// becomes : 
var clients = findClientsSocket();

// var clients = io.sockets.clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room');
Run Code Online (Sandbox Code Playgroud)

命名空间的 Api 变为:

// var clients = io.of('/chat').clients();
// becomes
var clients = findClientsSocket(null, '/chat');

// var clients = io.of('/chat').clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room', '/chat');
Run Code Online (Sandbox Code Playgroud)

另请参阅此相关问题,其中我提供了一个返回给定房间的套接字的函数.

function findClientsSocketByRoomId(roomId) {
var res = []
, room = io.sockets.adapter.rooms[roomId];
if (room) {
    for (var id in room) {
    res.push(io.sockets.adapter.nsp.connected[id]);
    }
}
return res;
}
Run Code Online (Sandbox Code Playgroud)

Socket.io 0.7

没有命名空间的 API :

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`
Run Code Online (Sandbox Code Playgroud)

对于命名空间

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`
Run Code Online (Sandbox Code Playgroud)

注意:由于socket.io API似乎容易破解,而某些解决方案依赖于实现细节,因此可能需要自己跟踪客户端:

var clients = [];

io.sockets.on('connect', function(client) {
    clients.push(client); 

    client.on('disconnect', function() {
        clients.splice(clients.indexOf(client), 1);
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 这次真是万分感谢.我很惊讶他们把这个功能拿出来了. (3认同)
  • @nha你的答案是完全正确的,但它不适用于带有redis商店服务器的多个节点.从1节点进程,您无法使用ns.connected [id]检查套接字是否连接 (3认同)

sal*_*nap 46

在socket.io 1.0之后我们无法使用

io.sockets.clients(); 
or
io.sockets.clients('room'); 
Run Code Online (Sandbox Code Playgroud)

了.相反,您可以使用以下内容

var clients_in_the_room = io.sockets.adapter.rooms[roomId]; 
for (var clientId in clients_in_the_room ) {
  console.log('client: %s', clientId); //Seeing is believing 
  var client_socket = io.sockets.connected[clientId];//Do whatever you want with this
}
Run Code Online (Sandbox Code Playgroud)

  • 我改为`varclients_in_the_room = io.sockets.adapter.rooms [roomId] .sockets` (3认同)

Jos*_*tra 36

使用Socket.IO 1.x:

获取连接客户端的数组:

io.engine === io.eio // => true
Object.keys(io.engine.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]
Object.keys(io.eio.clients)    // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]
Run Code Online (Sandbox Code Playgroud)

获取已连接客户端的数量:

io.engine.clientsCount // => 2
io.eio.clientsCount    // => 2
Run Code Online (Sandbox Code Playgroud)


小智 31

在socket.io 1.3中非常简单:

io.sockets.sockets - 是包含连接的套接字对象的数组.如果您在每个套接字中存储用户名,则可以执行以下操作:

io.sockets.sockets.map(function(e) {
    return e.username;
})
Run Code Online (Sandbox Code Playgroud)

繁荣.您拥有所有已连接用户的名称.

  • 这不适用于v1.4.5.仍在努力解决方案 (4认同)
  • 谢谢!+1 为简单起见。你知道这种方法和 Joseph Dykstra 的回答有什么区别吗?`(Object.keys(io.engine.clients)` (2认同)
  • TypeError:io.sockets.sockets.map不是函数 (2认同)

Cod*_* YT 25

更新 Socket.IO v4.0+(上次检查时间为 2024 年 2 月)

我已经尝试了所有其他答案......它们都不起作用,除了这个:

获取所有已连接套接字的最简单方法是通过:

await io.fetchSockets()
Run Code Online (Sandbox Code Playgroud)

它返回所有已连接套接字的数组

链接到用法和代码示例

希望能帮助到你!


Tha*_*yen 21

我今天经历了这种痛苦.如果他们可以为他们的API制作适当的文档,Socket.io会好得多.

无论如何,我试图调查io.sockets并找到了一些我们可以使用的选项:

io.sockets.connected //Return {socket_1_id: {}, socket_2_id: {}} . This is the most convenient one, since you can just refer to io.sockets.connected[id] then do common things like emit()
io.sockets.sockets //Returns [{socket_1}, {socket_2}, ....]. Can refer to socket_i.id to distinguish
io.sockets.adapter.sids //Return {socket_1_id: {}, socket_2_id: {}} . Looks similar to the first one but the object is not actually the socket, just the information.

// Not directly helps but still relevant
io.sockets.adapter.rooms //Returns {room_1_id: {}, room_2_id: {}}
io.sockets.server.eio.clients //Return client sockets
io.sockets.server.eio.clientsCount //Return number of connected clients
Run Code Online (Sandbox Code Playgroud)

另外,请注意当使用带有命名空间的socket.io时,由于io.sockets变为数组而不是对象,因此上述方法将会中断.要解决,只需用io替换io.sockets(即io.sockets.connected变为io.connected,io.sockets.adapter.rooms变为io.adapter.rooms ...)

在socket.io 1.3.5上测试过

  • 是的,官方文件可以改进得那么多 (2认同)

小智 17

我想我们可以从服务器访问套接字对象,你可以分配昵称,并指出它的套接字ID,

io.sockets.on('connection',function(socket){ 
    io.sockets.sockets['nickname'] = socket.id;
    client.on("chat", function(data) {      
        var sock_id = io.sockets.sockets['nickname']
        io.sockets.sockets[sock_id].emit("private", "message");
    });    
});
Run Code Online (Sandbox Code Playgroud)

disconnect请从删除昵称io.sockets.sockets.


Joh*_*alt 15

版本+2.0

在版本+2.0中,指定要查询的命名空间/房间/节点.

与广播一样,默认值是默认命名空间('/')中的所有客户端:

const io = require('socket.io')();  
io.clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});
Run Code Online (Sandbox Code Playgroud)

获取连接到特定命名空间的客户端ID列表(如果适用,则跨所有节点).

const io = require('socket.io')();
io.of('/chat').clients((error, clients) => {
     if (error) throw error;
     console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD]
});
Run Code Online (Sandbox Code Playgroud)

在命名空间的房间中获取所有客户端的示例:

const io = require('socket.io')();
io.of('/chat').in('general').clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [Anw2LatarvGVVXEIAAAD] 
});
Run Code Online (Sandbox Code Playgroud)

这来自官方文档:Socket.IO Server-API


ksl*_*oan 9

这是在socket.io 1.3中访问它的最佳方法

Object.keys(socket.adapter.rooms[room_id])


Gro*_*ogu 9

版本 4.0 及更高版本 (2021)

没有一个答案对我有用。我会让你免遭痛苦。自 1.0 以来,他们的 API 和文档发生了很大变化。

服务器 API:所有可用选项

但你需要在这里深入挖掘。

// Return all Socket instances
var clients = io.sockets;

clients.sockets.forEach(function(data, counter) {

    //console.log(data); // Maps

    var socketid = data.id; // Log ids
    var isConnected = data.connected // true, false;

});
Run Code Online (Sandbox Code Playgroud)

2023 年更新 - 获取所有已连接的用户

我想通过向您展示如何将用户 ID 附加到套接字 ID 以创建持久性(如果您需要它在项目中使用它(即:私人消息传递))来添加此答案。

client.js(客户端)

/***
*
*
* getConnectedUsers
*
*
*
*/
function getConnectedUsers(){
/**
*
*
* STEP 1
* GET
*
*
*/
//
var userID = localStorage.getItem('userid');//this typically would be the unique id from your database. Set this variable at login()
//set-username
socket.auth = { userID };
//console.log(socket.auth);
//
//get-connected-socket-users
socket.emit('get-connected-socket-users',{
userid:userID
});
}
/**
*
*
* STEP 2
* SET
* use this for instant communication
*
*/
socket.on('connected-socket-users',function(data){

//console.log(data);
var connectedUsers = JSON.stringify(data);

localStorage.setItem('connectedUsers',connectedUsers);
//console.log(localStorage.getItem('connectedUsers'));


});
Run Code Online (Sandbox Code Playgroud)

server.js(服务器端)

/**
* 
* 
* GET ALL CONNECTED USERS
* 
* 
*/
socket.on('get-connected-socket-users',function(data){
//
//variables
var userid = data.userid;
socket.username = userid;
//console.log(io.sockets);
//console.log(userid);
/**
* 
* GET ALL CONNECTED USERS
* 
*/
const users = [];
var clients = io.sockets;
clients.sockets.forEach(function(data,counter){

users.push({
userSocketID: data.id,
username: data.username,
});

});


//console.log(users);
//var handle = 
setInterval(function(){

socket.emit("connected-socket-users", users);

}, 3000);


// When you want to cancel it:
//clearInterval(handle);
//handle = 0; // I just do this so I know I've cleared the interval


});
Run Code Online (Sandbox Code Playgroud)


cri*_*eys 5

对于那些只想要COUNT个连接客户端的人,我相信这样做:

io.sockets.manager.server.connections

  • 为了获得准确的计数,请使用`io.sockets.clients().length` (5认同)
  • 目前`io.sockets.manager.server.connections` 和`io.sockets.clients().length` 都不起作用。这对我有用 - 仅用于计数 - `io.engine.clientsCount` 和客户端列表 - `io.engine.clientsCount`。因为它已经保持这种状态超过3年了。似乎是获取连接信息的可靠方法。(基于 Joseph Dykstra 的回答) (2认同)

小智 5

Socket.io 1.4.4

为您提供示例代码。

function get_clients_by_room(roomId, namespace) {
        io.of(namespace || "/").in(roomId).clients(function (error, clients) {
            if (error) { throw error; }
            console.log(clients[0]); // => [Anw2LatarvGVVXEIAAAD]
            console.log(io.sockets.sockets[clients[0]]); //socket detail
            return clients;
        });
    }
Run Code Online (Sandbox Code Playgroud)

我认为此代码块将对某人有所帮助。


小智 5

在Socket.IO 1.4中

要获取所有已连接用户的数组:

var allConnectedClients = Object.keys(io.sockets.connected); // This will return the array of SockeId of all the connected clients
Run Code Online (Sandbox Code Playgroud)

要获取所有客户端的计数:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients
Run Code Online (Sandbox Code Playgroud)