我正在尝试获取当前连接的所有套接字/客户端的列表。
不幸的是, io.sockets
没有返回数组。
我知道我可以使用数组保留自己的列表,但不要认为这是一个最佳解决方案有两个原因:
冗余。 Socket.IO已经保留了此列表的副本。
Socket.IO提供了为客户端设置任意字段值的方法(即:socket.set('nickname', 'superman')
)所以如果我要维护自己的列表,我需要跟上这些更改。
帮助?
答案 0 :(得分:160)
在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`
希望这有助于将来的某个人
注意:此解决方案仅适用于1.0之前的版本
答案 1 :(得分:93)
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;
}
无命名空间的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');
另请参阅此related question,其中我提供了一个返回给定房间的套接字的函数。
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似乎很容易破解,而某些解决方案依赖于实现细节,因此可能需要自己跟踪客户端:
var clients = [];
io.sockets.on('connect', function(client) {
clients.push(client);
client.on('disconnect', function() {
clients.splice(clients.indexOf(client), 1);
});
});
答案 2 :(得分:46)
在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
}
答案 3 :(得分:33)
使用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
答案 4 :(得分:31)
在socket.io 1.3中非常简单:
io.sockets.sockets
- 是包含已连接套接字对象的数组。
如果您在每个套接字中存储了用户名,则可以执行以下操作:
io.sockets.sockets.map(function(e) {
return e.username;
})
动臂。您拥有所有已连接用户的名称。
答案 5 :(得分: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
另外,请注意当使用带有命名空间的socket.io时,由于io.sockets变为数组而不是对象,因此上述方法将会中断。要解决,只需用io替换io.sockets(即io.sockets.connected变为io.connected,io.sockets.adapter.rooms变为io.adapter.rooms ......)
在socket.io 1.3.5上测试
答案 6 :(得分: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");
});
});
在disconnect
,请从io.sockets.sockets
删除昵称。
答案 7 :(得分:11)
在版本+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
答案 8 :(得分:9)
这是在socket.io 1.3
中访问它的最佳方法 Object.keys(socket.adapter.rooms[room_id])
答案 9 :(得分:5)
对于那些只想要COUNT个连接客户端的人,我相信会这样做:
io.sockets.manager.server.connections
答案 10 :(得分: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;
});
}
我认为这将有助于此代码阻止。
答案 11 :(得分:4)
在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
答案 12 :(得分:3)
从socket.io 1.5开始,请注意indexOf的变化,该变化似乎是de depreciated,并被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;
}
答案 13 :(得分:2)
没有一个答案对我有用。我会让你免于痛苦。从 1.0 开始,他们的 API 和文档发生了很大变化。
Server Api 所有可用选项
但你需要深入挖掘here
// 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;
});
答案 14 :(得分:2)
在socket.io 1.3上我已经完成了2行
var usersSocketIds = Object.keys(chat.adapter.rooms['room name']);
var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] })
答案 15 :(得分:2)
返回承诺
io.allSockets()
主命名空间中所有连接的套接字 id
io.in('room').allSockets()
// 'room' 中所有连接的 id
io.of('/namespace').allSockets()
// '/namespace' 中所有连接的 ids(你也可以将它与房间结合起来)
答案 16 :(得分:2)
socket.io@3.0
io.in('room1').sockets.sockets.forEach((socket,key)=>{
console.log(socket);
})
room1 中的所有 socket 实例
答案 17 :(得分:2)
function getConnectedList () { let list = [] for ( let client in io.sockets.connected ) { list.push(client) } return list } console.log( getConnectedList() ) // returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ]
答案 18 :(得分:1)
对于群集模式,使用redis-adapter
io.in(<room>).clients(function(err, clients) {
});
由于每个套接字本身都是一个房间,因此可以找到使用相同的套接字。
答案 19 :(得分:1)
对于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);
}
});
这仍然感觉不对,因为我一直有这种感觉与插座Io莫名其妙
答案 20 :(得分:1)
我相信你可以从socket的manager属性访问它吗?
var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;
答案 21 :(得分:1)
从版本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。
答案 22 :(得分:1)
如果您没有使用名称空间或房间,这是Socket.IO 1.0+中最简单的方法。
^ # Start
(?=.*[A-Z]) # lookahead to assert a capital letter
(?=.*[aAeEiIoOuU]) # lookahead to assert a vowel
(?=.*\d) # lookahead to assert a digit
(?: # non-capturing group start
([a-zA-Z\d]) # match any letter or digit and capture it in group #1
(?!\1) # negative lookahead to ensure same char is not repeated
)+ # non-capturing group end, + ensures 1 ore more of it
$ # end
这将查看默认命名空间并确定套接字数组的长度,而无需使用io.nsps["/"].sockets.length
答案 23 :(得分:1)
我在这里看到很多好的答案,很多很有用的地方,但不是我需要的。我正在使用socket作为pubsub功能,感兴趣的客户端可以监听给定记录中的任何更改。
我的具体问题是同一个插座多次加入同一个房间。对此的解决方案是检查插座是否已在其房间属性内具有房间。
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");
}
希望这有助于某人。
答案 24 :(得分:0)
如果项目有 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 page了解详情。
答案 25 :(得分:0)
我不知道这是否还在继续。但是这样的东西就是我最终使用的东西(我在每个连接的套接字上保留一个 session 对象,后者又包含用户名和其他信息:
var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
return io.sockets.connected[socketId].session.username;
});
答案 26 :(得分:0)
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 /用户名数组。
答案 27 :(得分:0)
v.10
var clients = io.nsps['/'].adapter.rooms['vse'];
/*
'clients' will return something like:
Room {
sockets: { '3kiMNO8xwKMOtj3zAAAC': true, FUgvilj2VoJWB196AAAD: true },
length: 2 }
*/
var count = clients.length; // 2
var sockets = clients.map((item)=>{ // all sockets room 'vse'
return io.sockets.sockets[item];
});
sample >>>
var handshake = sockets[i].handshake;
handshake.address .time .issued ... etc.
答案 28 :(得分:0)
以下是使用ES6生成器将连接套接字的哈希值从命名空间转换为数组的快速方法(适用于socket.io&gt; = 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
})
答案 29 :(得分:0)
io.sockets.sockets.keys()
这对我有帮助。
答案 30 :(得分:0)
socket.io 4.0.0 版
在服务器端列出我使用的所有活动套接字的一些属性:
function listSocketsProperty(myProperty){
let sck = io.sockets.sockets
const mapIter = sck.entries()
while(1){
let en = mapIter.next().value?.[0]
if(en) console.log( sck.get(en)[myProperty] )
else break
}
}
说明:
sck=io.sockets.sockets 是一个 Map 对象。
entries() 方法返回一个新的 Iterator 对象,该对象包含 Map 对象中每个元素的 [key, value] 对。
en=mapIter.next().value?.[0]获取 key - pair 的第一个元素。
如果没有更多的迭代,en 变为 undefined,这会中断 while 循环。
示例:
我的套接字有属性“playerName”,我想列出所有房间中所有活跃玩家的名字。为此,我只需调用函数:
listSocketsProperty('playerName')
然后进入控制台,如下所示:
John
Peter
Zoran
etc.