Розетка.IO-как получить список подключенных сокетов / клиентов?
Я пытаюсь получить список всех сокетов / клиентов, которые в настоящее время подключены.
io.sockets
не возвращает массив, к сожалению.
Я знаю, что могу сохранить свой собственный список, используя массив, но не думаю, что это оптимальное решение по 2 причинам:
избыточности. Розетка.IO уже хранит копию этого списка.
розетка.IO предоставляет метод для установки произвольных значений полей для клиентов (i.e:
socket.set('nickname', 'superman')
) так Мне нужно будет идти в ногу с этими изменениями, если я хочу сохранить свой собственный список.
помочь?
27 ответов
В Гнезде.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
розетка.io 1.4
Object.keys(io.sockets.sockets);
дает вам все подключенные сокеты.
розетка.io 1.0 Как из розетки.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');
Также см. Этот обзоры вопрос, в котором я даю функцию, которая возвращает сокеты для данной комнаты.
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;
}
розетка.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`
Примечание: так как это кажется сокетом.IO API склонен к нарушению, и некоторые решения полагаются на детали реализации, это может быть вопрос отслеживания клиентов самостоятельно:
var clients = [];
io.sockets.on('connect', function(client) {
clients.push(client);
client.on('disconnect', function() {
clients.splice(clients.indexOf(client), 1);
});
});
Через Сокет.ИО 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
очень просто в гнезде.Ио 1.3:
io.sockets.sockets
- массив, содержащий подключенные объекты сокетов.
Если вы сохранили имя пользователя в каждом сокете, вы можете сделать:
io.sockets.sockets.map(function(e) {
return e.username;
})
бум. У вас есть имена всех подключенных пользователей.
Я прошел через эту боль сегодня. Розетка.io будет намного лучше, если они смогут сделать надлежащую документацию для своего API.
в любом случае, я попытался заглянуть в io.сокеты и нашел ряд вариантов, которые мы можем использовать:
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
Также обратите внимание, что при использовании сокета.io с пространством имен, вышеуказанные методы будут ломаться с io.sockets становится массивом вместо объекта. Чтобы решить, просто замените io.сокеты по io (i.e io.розетки.подключен становится Ио.связанный, Ио.розетки.адаптер.номера становится Ио.адаптер.комнаты...)
протестировано на сокете.io 1.3.5
Я думаю, что мы можем получить доступ к объекту сокета с сервера, и вы можете назначить псевдоним и указать его идентификатор сокета,
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");
});
});
On disconnect
удалите Ник из io.sockets.sockets
.
для тех, кто просто хочет подсчета подключенных клиентов, я считаю, что это сделает это:
io.sockets.manager.server.connections
гнездо.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;
});
}
Я думаю, поможет кому-то этот блок кода.
версия +2.0
в версии + 2.0 вы указываете пространство имен / комнату / узел, к которому вы обращаетесь.
как и при трансляции, по умолчанию все клиенты из пространства имен по умолчанию ('/'):
const io = require('socket.io')();
io.clients((error, clients) => {
if (error) throw error;
console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});
возвращает список идентификаторов клиентов, подключенных к определенному пространству имен (по всем узлам, если применимо).
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]
});
Это из официальной документации:гнездо.IO Server-API
В Гнезде.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
по состоянию на сокет.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;
}
для гнезда.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;
}
на сокете.io 1.3 я выполнил это в 2 строках
var usersSocketIds = Object.keys(chat.adapter.rooms['room name']);
var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] })
гнездо.io 1.7.3 (+):
function getConnectedList () { let list = [] for ( let client in io.sockets.connected ) { list.push(client) } return list } console.log( getConnectedList() ) // returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ]
Я считаю, что вы можете получить доступ к этому из свойства менеджера сокета?
var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;
Я вижу много хороших ответов здесь и много где очень полезно, но не совсем то, что мне нужно. Я использую сокеты для функции 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");
}
надеюсь, это кому-то поможет.
начиная с версии 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...
}
});
по какой-то причине они используют простой объект вместо массива для хранения идентификаторов сокетов.
для версии 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);
}
});
все еще это не кажется правильным, так как у меня всегда есть это чувство с socket Io как-то
для режима кластера, используя redis-adaptor
io.in(<room>).clients(function(err, clients) {
});
поскольку каждый сокет сам по себе является комнатой, поэтому можно найти, существует ли сокет, используя то же самое.
вот быстрый способ преобразовать хэш подключенных сокетов из пространства имен в массив с помощью генераторов ES6 (применяется к сокету.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
})
Это самый простой способ в сокете.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;
});
Если проект имеет гнездо.Ио кластер это означает гнездо.io-redis адаптер используется.
Если случай, как указано выше, получение всех подключенных сокетов id процесс должен быть применен через гнездо.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);
});
пожалуйста, посетите гнездо.io-redis GitHub страница для получения более подробной информации.
var Client = require("socket.io").listen(8888); //port listening
//This is the best way.
var connection = Client.engine.clientsCount
socket.io@1.7.3
я использовал объект.Ключи для подключения массива сокетов. Затем в том же массиве итерации с функцией 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);
возможно, этот ответ может помочь получить массив идентификатора сокета / имени пользователя.
В. 10
var clients = io.nsps['/'].adapter.rooms['vse'];
var count = clients.length; // count
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.