Socket.IO – come ottengo un elenco di socket / client connessi?

Sto cercando di ottenere un elenco di tutti i socket / client attualmente connessi.

io.sockets non restituisce un array, sfortunatamente.

So che potrei mantenere la mia lista usando un array, ma non penso che questa sia una soluzione ottimale per 2 motivi:

  1. Ridondanza. Socket.IO conserva già una copia di questa lista.

  2. Socket.IO fornisce un metodo per impostare valori di campo arbitrari per i client (es .: socket.set('nickname', 'superman') ) quindi dovrei tenere il passo con queste modifiche se dovessi mantenere la mia lista.

Aiuto?

In Socket.IO 0.7 si ha un metodo clients sugli spazi dei nomi, questo restituisce una matrice di tutti i socket connessi.

API per nessuno spazio dei nomi:

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

Per uno spazio dei nomi

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

Spera che questo aiuti qualcuno in futuro

NOTA: questa soluzione funziona SOLO con la versione precedente alla 1.0

Socket.io 1.4

Object.keys(io.sockets.sockets); ti dà tutte le prese collegate.

Socket.io 1.0 A partire da socket.io 1.0, la risposta effettiva accettata non è più valida. Quindi ho creato una piccola funzione che uso come correzione temporanea:

 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 per Nessun spazio dei nomi diventa

 // 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 per uno spazio dei nomi diventa:

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

Vedi anche questa domanda correlata , in cui do una funzione che restituisce le prese per una data stanza.

 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 per nessuno spazio dei nomi :

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

Per uno spazio dei nomi

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

Nota: poiché sembra che l’API socket.io sia soggetta a rotture, e alcune soluzioni si basano sui dettagli di implementazione, potrebbe essere una questione di tracciabilità dei client:

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

Dopo socket.io 1.0 non possiamo usare

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

più. Invece è ansible utilizzare il seguente

 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 } 

Utilizzando Socket.IO 1.x:

Ottieni un array dei client connessi:

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

Ottieni il numero di client connessi:

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

Molto semplice in socket.io 1.3:

io.sockets.sockets : è una matrice contenente gli oggetti socket connessi. Se hai memorizzato il nome utente in ciascun socket, puoi fare:

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

Boom. Hai i nomi di tutti gli utenti connessi.

Ho passato questo dolore oggi. Socket.io sarà molto meglio se potesse fare una documentazione adeguata per la loro API.

Ad ogni modo, ho provato a cercare in io.socket e ho trovato un certo numero di opzioni che possiamo usare:

 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 

Inoltre, si noti che quando si utilizza socket.io con namespace, i metodi precedenti si interromperanno poiché io.sockets diventa una matrice invece di un object. Per risolvere, basta sostituire io.sockets con io (cioè io.sockets.connected diventa io.connected, io.sockets.adapter.rooms diventa io.adapter.rooms …)

Testato su socket.io 1.3.5

Penso che possiamo accedere all’object socket dal server, e puoi assegnare il nickname e puntare il suo ID 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"); }); }); 

Alla disconnect , rimuovere il nickname da io.sockets.sockets .

Questo è il modo migliore per accedervi in ​​socket.io 1.3

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

Per tutti quelli che vogliono solo un COUNT dei client connessi, credo che lo faranno:

io.sockets.manager.server.connections

Socket.io 1.4.4

Codice di esempio per voi

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

Penso che aiuterà qualcuno questo blocco di codice.

Versione +2.0

Nella versione +2.0 si specifica lo spazio dei nomi / sala / nodo su cui si sta eseguendo una query.

Come per la trasmissione, l’impostazione predefinita è tutti i client dallo spazio dei nomi predefinito (‘/’):

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

Ottiene un elenco di ID client connessi a uno spazio dei nomi specifico (su tutti i nodes, se applicabile).

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

Un esempio per ottenere tutti i client nella stanza dello spazio dei nomi:

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

Questo è dalla documentazione ufficiale: Socket.IO Server-API

In Socket.IO 1.4

Per ottenere l’array di Tutti gli utenti connessi:

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

Per ottenere il conteggio di tutti i clienti:

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

A partire da socket.io 1.5, si noti la modifica da indexOf che appare deprecata e sostituita da 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; } 

Per socket.io versione 2.0.3, il seguente codice funziona:

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

su socket.io 1.3 ho realizzato questo in 2 righe

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

Socket.io 1.7.3 (+):

 function getConnectedList ()
 {
     let list = []

     per (lascia il client in io.sockets.connected)
     {
         list.push (client)
     }

     lista di ritorno
 }

 console.log (getConnectedList ())

 // restituisce ['yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB']

Credo che tu possa accedervi dalla proprietà del gestore del socket?

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

Vedo molte buone risposte qui e molte in cui è abbastanza utile ma non proprio quello di cui avevo bisogno. Sto usando i socket per una funzione pubsub in cui un client interessato può ascoltare qualsiasi modifica in un determinato record.

Il mio problema specifico era che lo stesso socket si stava unendo alla stessa stanza più volte. La soluzione a questo era verificare se la presa avesse già la stanza nella sua proprietà.

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

Spero che questo aiuti qualcuno.

Dalla versione 1.5.1, sono in grado di accedere a tutti i socket in uno spazio dei nomi 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... } }); 

Per qualche ragione, stanno usando un object semplice invece di una matrice per memorizzare gli ID dei socket.

Per la versione 2.3 funziona e ti prenderà anche il socket , mi sembra che socketIo stia cambiando troppo velocemente e con una documentazione poco leggibile dopo averlo usato per un po ‘.

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

ancora questo non mi sembra giusto, come ho sempre avuto questa sensazione con il socket Io in qualche modo

Per la modalità cluster, usando redis-adapter

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

Poiché ogni socket è esso stesso una stanza, così si può scoprire se esiste un socket che usa lo stesso.

Ecco un modo rapido per convertire l’hash dei socket connessi da un namespace in un array usando i generatori ES6 (si applica 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 }) 

Questo è il modo più semplice in Socket.IO 1.0+, se non si utilizzano spazi dei nomi o stanze.

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

Questo guarda lo spazio dei nomi predefinito e determina la lunghezza dell’array dei socket, senza bisogno di usare Object.keys()

Non so se questo è ancora in corso. Ma qualcosa del genere è quello che ho finito usando (tengo un object session su ogni socket connesso, che a sua volta contiene il nome utente e altre informazioni:

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

Se il progetto ha un cluster socket.io , questo significa che viene utilizzato l’adattatore socket.io-redis .

Se il caso come sopra, ottenere la procedura di identificazione di tutti i socket connessi deve essere applicato tramite l’adattatore socket.io-redis . Gli esempi seguenti potrebbero essere utilizzati per questo;

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

Visita la pagina github socket.io-redis per maggiori dettagli.

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