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

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

io.sockets 不幸的是,它不返回数组。

我知道我可以使用数组保留自己的列表,但是由于以下两个原因,这并不是最佳解决方案:

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

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

救命?

猴子村村2020/04/03 10:37:22

如果项目具有socket.io群集,则意味着正在使用socket.io-redis适配器。

如果是上述情况,则必须通过socket.io-redis适配器执行获取所有已连接套接字id的过程以下示例可用于此目的;

io.of('/').adapter.clients(function (err, clients) {
  console.log("clients: ", clients); // an array containing all connected socket ids
});


io.of('/').adapter.allRooms(function (err, rooms) {
  console.log("all rooms: ", rooms);
});

请访问socket.io-redis github页面以获取更多详细信息。

路易Pro2020/04/03 10:37:22

我不知道这是否还会继续。但是我最终使用的是这样的东西(我在每个连接的套接字上保留一个会话对象,而该对象又包含用户名和其他信息:

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return io.sockets.connected[socketId].session.username;
});
斯丁理查德2020/04/03 10:37:22

socket.io@1.7.3

我使用Object.Keys来获取连接的套接字数组。然后在同一数组中使用map函数进行迭代以构建新的对象数组

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return { socket_id : socketId, socket_username: io.sockets.connected[socketId].username };
});

// test
console.log(connectedUsers);

也许这个答案可以帮助获得套接字ID /用户名数组。

十三西门小小2020/04/03 10:37:22

如果不使用名称空间或房间,这是Socket.IO 1.0+中最简单的方法。

io.nsps["/"].sockets.length

这将检查默认名称空间并确定套接字数组的长度,而无需使用 Object.keys()

Pro宝儿2020/04/03 10:37:22

对于集群模式,使用redis-adaptor

io.in(<room>).clients(function(err, clients) {

});

由于每个插槽本身就是一个房间,因此可以使用该插槽查找是否存在插槽。

凯ANear2020/04/03 10:37:21

对于2.3版本,它可以正常工作,并且也会为您提供套接字,在我看来,一段时间使用后,socketIo的更改速度太快,几乎没有可读的文档。

ioSite.of('/').in(roomId).clients((error, clients) => {
    if (error) throw error;
    for (var i=0;i<clients.length;i++) {
        clientId=clients[i];
        console.log(clientId);

        // load the socket of your namespace
        var socket=ioSite.of('/').in(roomId).connected[clientId]
        console.log(socket.constructor.name);
        console.log(socket.id);
    }
});

仍然感觉不对,因为我总是对套接字有这种感觉

古一2020/04/03 10:37:21

我相信您可以从套接字的manager属性访问此对象?

var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;
卡卡西2020/04/03 10:37:21

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

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

宝儿理查德2020/04/03 10:37:21

在Socket.IO 1.4中

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

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

要获得所有客户的数量:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients
逆天LEY2020/04/03 10:37:21

对于只需要COUNT个连接的客户端的人,我相信这可以做到:

io.sockets.manager.server.connections

Gil伽罗小宇宙2020/04/03 10:37:21

从socket.io 1.5开始,请注意对indexOf的更改似乎已过时,并已替换为valueOf

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

    if (ns) {
        for (var id in ns.connected) {
            if (roomId) {
                //var index = ns.connected[id].rooms.indexOf(roomId) ;
                var index = ns.connected[id].rooms.valueOf(roomId) ; //Problem was here

                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res.length;
}

对于socket.io 2.0.3版,以下代码适用:

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

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                // ns.connected[id].rooms is an object!
                var rooms = Object.values(ns.connected[id].rooms);  
                var index = rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            }
            else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}
Mandy2020/04/03 10:37:21

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

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

Gil伽罗小宇宙2020/04/03 10:37:21

在socket.io 1.3中非常简单:

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

io.sockets.sockets.map(function(e) {
    return e.username;
})

繁荣。您具有所有已连接用户的名称。

番长樱梅2020/04/03 10:37:20

我今天经历了这种痛苦。如果他们可以为其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

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

在socket.io 1.3.5上测试