Socket.IO: ¿cómo obtengo una lista de sockets / clientes conectados?

Estoy tratando de obtener una lista de todos los sockets / clientes que están conectados actualmente.

io.sockets no devuelve una matriz, desafortunadamente.

Sé que podría mantener mi propia lista usando una matriz, pero no creo que esta sea una solución óptima por dos razones:

  1. Redundancia. Socket.IO ya tiene una copia de esta lista.

  2. Socket.IO proporciona un método para establecer valores de campo arbitrarios para los clientes (es decir: socket.set('nickname', 'superman') ), así que tendría que estar al día con estos cambios si tuviera que mantener mi propia lista.

¿Ayuda?

En Socket.IO 0.7 tiene un método de clients en los espacios de nombres, esto devuelve una matriz de todos los sockets conectados.

API para no espacio de nombres:

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

Para un espacio de nombres

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

Espera que esto ayude a alguien en el futuro

NOTA: Esta solución SÓLO funciona con la versión anterior a la 1.0

Socket.io 1.4

Object.keys(io.sockets.sockets); te da todos los sockets conectados.

Socket.io 1.0 A partir de socket.io 1.0, la respuesta aceptada real ya no es válida. Así que hice una pequeña función que utilizo como solución temporal:

 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 for No namespace se convierte

 // 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 para un espacio de nombres se convierte en:

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

También vea esta pregunta relacionada , en la que doy una función que devuelve los sockets para una habitación determinada.

 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 para no espacio de nombres :

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

Para un espacio de nombres

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

Nota: Dado que parece que la API de socket.io es propensa a romperse, y alguna solución depende de los detalles de la implementación, podría ser cuestión de hacer un seguimiento de los clientes usted mismo:

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

Después de socket.io 1.0 no podemos usar

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

nunca más. En su lugar, puede usar lo siguiente

 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 } 

Usando Socket.IO 1.x:

Obtener una matriz de los clientes conectados:

 io.engine === io.eio // => true Object.keys(io.engine.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ] Object.keys(io.eio.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ] 

Obtenga la cantidad de clientes conectados:

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

Muy simple en socket.io 1.3:

io.sockets.sockets – es una matriz que contiene los objetos de socket conectados. Si almacenó el nombre de usuario en cada socket, puede hacer:

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

Auge. Usted tiene los nombres de todos los usuarios conectados.

He pasado por este dolor hoy. Socket.io será mucho mejor si pudieran hacer una documentación adecuada para su API.

De todos modos, traté de buscar en io.sockets y encontré una cantidad de opciones que podemos usar:

 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 

Además, tenga en cuenta que al usar socket.io con namespace, los métodos anteriores se romperán ya que io.sockets se convierte en una matriz en lugar de en un objeto. Para resolver, simplemente reemplace io.sockets por io (es decir, io.sockets.connected se convierte io.connected, io.sockets.adapter.rooms se convierte en io.adapter.rooms …)

Probado en socket.io 1.3.5

Creo que podemos acceder al objeto de socket desde el servidor, y puede asignar el alias, y apuntar su ID de socket,

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

Al disconnect , elimine el sobrenombre de io.sockets.sockets .

Esta es la mejor manera de acceder a ella en socket.io 1.3

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

Para cualquiera que solo quiera un COUNT de clientes conectados, creo que esto lo hará:

io.sockets.manager.server.connections

Socket.io 1.4.4

Código de muestra para ti

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

Creo que ayudará a alguien bloquear este código.

Versión +2.0

En la versión +2.0 especifica el espacio de nombres / sala / nodo sobre el que está consultando.

Al igual que con la radiodifusión, el valor predeterminado es todos los clientes del espacio de nombre predeterminado (‘/’):

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

Obtiene una lista de ID de cliente conectadas al espacio de nombre específico (en todos los nodos, si corresponde).

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

Un ejemplo para obtener todos los clientes en la sala del espacio de nombres:

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

Esto es de la documentación oficial: Socket.IO Server-API

En Socket.IO 1.4

Para obtener la matriz de Todos los usuarios conectados:

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

Para obtener el conteo de todos los clientes:

 var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients 

A partir de socket.io 1.5, observe el cambio de indexOf que parece depreciado y reemplazado por 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; } 

Para socket.io versión 2.0.3, funciona el siguiente código:

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

en socket.io 1.3 lo he logrado en 2 líneas

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

Socket.io 1.7.3 (+):

 función getConnectedList ()
 {
     let list = []

     para (deje al cliente en io.sockets.connected)
     {
         list.push (cliente)
     }

     lista de regreso
 }

 console.log (getConnectedList ())

 // devuelve ['yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB']

Creo que puede acceder a esto desde la propiedad del administrador del socket.

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

Veo muchas buenas respuestas aquí y muchas fueron bastante útiles pero no exactamente lo que necesitaba. Estoy usando sockets para una función pubsub en la que un cliente interesado puede escuchar cualquier cambio en un registro determinado.

Mi problema específico era que el mismo socket se estaba uniendo a la misma sala varias veces. La solución a esto era verificar si el socket ya tenía la habitación dentro de la propiedad de las habitaciones.

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

Espero que esto ayude a alguien.

A partir de la versión 1.5.1, puedo acceder a todos los sockets en un espacio de nombres con:

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

Por alguna razón, están usando un objeto simple en lugar de una matriz para almacenar los ID de los sockets.

Para la versión 2.3 esto funciona y también obtendrá el socket , me parece que socketIo está cambiando demasiado rápido y con poca documentación legible después de usarlo por un tiempo.

 ioSite.of('/').in(roomId).clients((error, clients) => { if (error) throw error; for (var i=0;i 

Todavía esto no se siente bien, ya que siempre tengo esta sensación con socket Io de alguna manera

Para el modo de clúster, usando redis-adapter

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

Como cada zócalo es en sí mismo una habitación, uno puede encontrar si existe un zócalo usando el mismo.

Esta es una forma rápida de convertir el hash de los sockets conectados de un espacio de nombres a un array que usa generadores ES6 (se aplica a 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 }) 

Esta es la forma más simple en Socket.IO 1.0+, si no está usando espacios de nombres o salas.

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

Esto mira el espacio de nombres predeterminado y determina la longitud de la matriz de sockets, sin la necesidad de utilizar Object.keys()

No sé si esto todavía está sucediendo. Pero algo así es lo que terminé usando (guardo un objeto de sesión en cada socket conectado, que a su vez contiene el nombre de usuario y otra información:

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

Si el proyecto tiene un clúster socket.io, esto significa que se está utilizando el adaptador socket.io-redis .

Si el caso es similar al anterior, se debe aplicar el proceso de identificación de sockets conectado a través del adaptador socket.io-redis . Los siguientes ejemplos pueden ser utilizados para esto;

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

Por favor visite la página de socket.io-redis github para más detalles.

 var Client = require("socket.io").listen(8888); //port listening //This is the best way. var connection = Client.engine.clientsCount