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

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

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

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

  1. 冗余。 Socket.IO已经保存了这个列表的副本。

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

帮帮我?

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

没有命名空间的API:

 var clients = io.sockets.clients(); var clients = io.sockets.clients('room'); // all users from room `room` 

对于命名空间

 var clients = io.of('/chat').clients(); var clients = io.of('/chat').clients('room'); // all users from room `room` 

希望这有助于未来的人

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

Socket.io 1.4

Object.keys(io.sockets.sockets); 给你所有连接的套接字。

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

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

没有命名空间的 Api变成了

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

一个名称空间的 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'); 

也看到这个相关的问题 ,我给一个函数返回给定的房间的套接字。

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

Socket.io 0.7

没有命名空间的 API:

 var clients = io.sockets.clients(); var clients = io.sockets.clients('room'); // all users from room `room` 

对于命名空间

 var clients = io.of('/chat').clients(); var clients = io.of('/chat').clients('room'); // all users from room `room` 

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

 var clients = []; io.sockets.on('connect', function(client) { clients.push(client); client.on('disconnect', function() { clients.splice(clients.indexOf(client), 1); }); }); 

在socket.io 1.0之后,我们不能使用

 io.sockets.clients(); or io.sockets.clients('room'); 

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

 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 } 

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

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

 io.engine.clientsCount // => 2 io.eio.clientsCount // => 2 

在socket.io 1.3中很简单:

io.sockets.sockets – 是一个包含连接的套接字对象的数组。 如果你在每个套接字中存储了用户名,你可以这样做:

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

繁荣。 你有所有连接的用户的名字。

我想我们可以从服务器访问套接字对象,并且可以分配昵称,并指向它的套接字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"); }); }); 

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

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

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

 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.socketsreplace为io(即io.sockets.connected变为io.connected,io.sockets.adapter.rooms变成io.adapter.rooms …)

在socket.io 1.3.5上testing

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

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

对于任何人只是想连接的客户端计数,我相信这将做到这一点:

io.sockets.manager.server.connections

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

我认为会帮助这个代码块的人。

在socket.io 1.3我已经完成了这两行

 var usersSocketIds = Object.keys(chat.adapter.rooms['room name']); var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] }) 

在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 

Socket.io 1.7.3(+):

函数getConnectedList()
 {
    让list = []

    为(让客户端在io.sockets.connected)
     {
         list.push(客户端)
     }

    返回列表
 }

 console.log(getConnectedList())

 //返回['yIfhb2tw7mxgrnF6AAAA','qABFaNDSYknCysbgAAAB']

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

我相信你可以从套接字的pipe理器属性访问它?

 var handshaken = io.manager.handshaken; var connected = io.manager.connected; var open = io.manager.open; var closed = io.manager.closed; 

我在这里看到很多很好的答案,很多地方很有用,但不是我所需要的。 我正在使用套接字作为pubsubfunction,感兴趣的客户端可以侦听给定logging中的任何更改。

我的具体问题是同一个套接字几次join同一个房间。 解决scheme是检查套接字是否已经在房间内的房间。

 var room = myObj.id.toString(); if (socket.rooms.indexOf(room) === -1) { socket.join(room); socket.emit('subscribed', {to : room}); } else { console.log("Already in room"); } 

希望这有助于某人。

从版本1.5.1开始,我可以通过以下方式访问命名空间中的所有套接字:

 var socket_ids = Object.keys(io.of('/namespace').sockets); socket_ids.forEach(function(socket_id) { var socket = io.of('/namespace').sockets[socket_id]; if (socket.connected) { // Do something... } }); 

出于某种原因,他们使用普通对象而不是数组来存储套接字ID。

对于版本2.3这个工作,它也会得到你的套接字 ,在我看来,socketIo正在改变太快,并使用一段时间后,很less有可读的文件。

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

不过这个感觉不对,因为我总是对socketsIo有这种感觉

这里是一个快速的方法来将连接的套接字从一个名字空间转换成一个使用ES6生成器的数组(适用于socket.io> = v1.0.0):

 io.on('connection', function(socket) { var hash = io.of('/').connected var list = null hash[Symbol.iterator] = function*() { // for..of loop to invoke Object.keys() default iterator // to get the array values instead of the keys for(var id of Object.keys(hash)) yield hash[id] } list = [...hash] console.log(Array.isArray(list)) // true }) 

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

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

这看着默认的命名空间,并确定了套接字数组的长度,而不需要使用Object.keys()

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

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

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

如果情况如上所述,获取所有连接的套接字ID进程必须通过socket.io-redis适配器应用。 下面的例子可能用于这个;

 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页面了解更多详情。

版本+2.0

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

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

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

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

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

获取名称空间中所有客户端的示例:

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

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

var Client = require(“socket.io”)。listen(8888);

//这是最好的方法

var connection = Client.engine.clientsCount

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

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

由于每个套接字本身就是一个房间,因此可以使用相同的方法来查找套接字是否存在。