web-dev-qa-db-fra.com

Socket.IO - Comment puis-je obtenir une liste des sockets/clients connectés?

J'essaie d'obtenir une liste de tous les sockets/clients actuellement connectés. 

io.sockets ne retourne malheureusement pas de tableau. 

Je sais que je pourrais garder ma propre liste en utilisant un tableau, mais je ne pense pas que ce soit une solution optimale pour 2 raisons:

  1. Redondance. Socket.IO conserve déjà une copie de cette liste.

  2. Socket.IO fournit une méthode pour définir des valeurs de champ arbitraires pour les clients (c'est-à-dire: socket.set('nickname', 'superman')). Je devrais donc suivre ces modifications si je tenais à jour ma propre liste.

Aidez-moi?

138
Andy Hin

Dans Socket.IO 0.7, vous avez une méthode clients sur les espaces de noms, elle renvoie un tableau de tous les sockets connectés.

API pour aucun espace de noms:

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

Pour un espace de noms

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

Espère que cela aide quelqu'un à l'avenir

NOTE: Cette solutionSEULEMENTfonctionne avec les versions antérieures à 1.0

158
3rdEden

Socket.io 1.4

Object.keys(io.sockets.sockets); vous donne tous les sockets connectés.

Socket.io 1.0 Depuis socket.io 1.0, la réponse acceptée n'est plus valide . J'ai donc créé une petite fonction que j'utilise comme solution temporaire:

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 devient 

// 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 pour un espace de noms devient:

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

Voir aussi cette question liée }, dans laquelle je donne une fonction qui renvoie les sockets pour une pièce donnée.

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 pour pas d’espace de nom:

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

Pour un espace de noms

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

Remarque: Comme il semble que l'API socket.io soit sujette à la rupture, et qu'une solution repose sur des détails d'implémentation, il peut s'agir de suivre vous-même les clients:

var clients = [];

io.sockets.on('connect', function(client) {
    clients.Push(client); 

    client.on('disconnect', function() {
        clients.splice(clients.indexOf(client), 1);
    });
});
91
nha

Après socket.io 1.0, nous ne pouvons pas utiliser 

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

plus. Au lieu de cela, vous pouvez utiliser ce qui suit 

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
}
45
salihcenap

Utilisation de Socket.IO 1.x:

Obtenir un tableau des clients connectés:

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

Obtenez le nombre de clients connectés:

io.engine.clientsCount // => 2
io.eio.clientsCount    // => 2
32
Joseph Dykstra

Très simple dans socket.io 1.3:

io.sockets.sockets - est un tableau contenant les objets socket connectés . Si vous avez stocké le nom d'utilisateur dans chaque socket, vous pouvez effectuer les opérations suivantes:

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

Boom. Vous avez les noms de tous les utilisateurs connectés. 

30
or29544

J'ai traversé cette douleur aujourd'hui. Socket.io sera bien mieux s’ils peuvent créer une documentation appropriée pour leur API.

Quoi qu'il en soit, j'ai essayé de regarder dans io.sockets et trouvé un certain nombre d'options que nous pouvons utiliser:

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

De plus, notez que lorsqu’on utilise socket.io avec un espace de noms, les méthodes ci-dessus ne fonctionneront plus car io.sockets devient un tableau au lieu d’un objet. Pour résoudre ce problème, remplacez simplement io.sockets par io (i.e. io.sockets.connected devient io.connected, io.sockets.adapter.rooms devient io.adapter.rooms ...).

Testé sur socket.io 1.3.5

21
Thanh Nguyen

Je pense que nous pouvons accéder à l'objet socket depuis le serveur, et vous pouvez attribuer le surnom et pointer son identifiant 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");
    });    
});

Sur disconnect, supprimez le pseudo de io.sockets.sockets.

17
sunil n jose

Version +2.0

Dans la version +2.0, vous spécifiez l'espace de nom/la pièce/le noeud sur lequel vous interrogez.

Comme pour la diffusion, tous les clients de l'espace de noms par défaut ('/') sont définis par défaut:

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

Obtient une liste d'ID clients connectés à un espace de noms spécifique (sur tous les nœuds, le cas échéant).

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

Un exemple pour obtenir tous les clients dans la salle de l'espace de noms:

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

Ceci est tiré de la documentation officielle: Socket.IO Server-API

7
John Galt

Pour ceux qui veulent juste un nombre de clients connectés, je crois que cela va le faire:

io.sockets.manager.server.connections

5
crickeys

Socket.io 1.4.4

Exemple de code pour vous.

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

Je pense que cela aidera quelqu'un à bloquer ce code.

4
Tiago Zamperini

Dans Socket.IO 1.4 

Pour obtenir le tableau de tous les utilisateurs connectés:

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

Pour obtenir le nombre de tous les clients:

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

A partir de socket.io 1.5, notez le passage de indexOf qui semble déprécié et remplacé par 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;
}

Pour socket.io version 2.0.3, le code suivant fonctionne:

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

sur socket.io 1.3 j'ai accompli cela en 2 lignes

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

Socket.io 1.7.3 (+):

 function getConnectedList () 
 {
 let list = [] 

 for (laissez le client dans io.sockets.connected) 
 {
 list.Push (client) 
 } 

 liste de retour 
} 

 console.log (getConnectedList ()) 

 // renvoie ['yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB'] 

2

Pour le mode cluster, en utilisant redis-adapter 

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

});

Comme chaque prise est elle-même une pièce, il est donc possible de déterminer s’il existe une prise utilisant la même.

1
Anuj Nautiyal

C'est la manière la plus simple de Socket.IO 1.0+, si vous n'utilisez pas d'espaces de noms ou de salles.

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

Ceci regarde l'espace de noms par défaut et détermine la longueur du tableau de sockets, sans avoir besoin d'utiliser Object.keys()

1
suncannon

Pour la version 2.3, cela fonctionne et vous obtiendrez également le socket , il me semble que le socketIo change trop rapidement et avec trop peu de documentation lisible après l'avoir utilisé pendant un certain temps. 

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

toujours cela ne me semble pas juste, comme j'ai toujours ce sentiment avec le socket Io

1
Joris Ceelen

Depuis la version 1.5.1, je peux accéder à tous les sockets d'un espace de noms avec:

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

Pour une raison quelconque, ils utilisent un objet brut au lieu d'un tableau pour stocker les ID de socket.

1
rppc

Je vois beaucoup de bonnes réponses ici et beaucoup d’entre elles sont très utiles mais pas tout à fait ce dont j'avais besoin. J'utilise des sockets pour une fonction pubsub dans laquelle un client intéressé peut écouter les modifications apportées à un enregistrement donné.

Mon problème spécifique était que la même prise rejoignait la même pièce plusieurs fois. La solution à cela était de vérifier si la prise avait déjà la pièce dans ses pièces.

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

J'espère que ça aide quelqu'un.

1
Gus Ortiz

Je crois que vous pouvez y accéder à partir de la propriété du gestionnaire du socket.

var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;
1
Dan Steele

Si le projet a un cluster socket.io, cela signifie que l'adaptateur socket.io-redis est utilisé.

Si tel est le cas, obtenir le processus de connexion de tous les sockets connectés doit être appliqué via l’adaptateur socket.io-redis. Les exemples ci-dessous peuvent être utilisés pour cela;

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

S'il vous plaît visitez socket.io-redis github page pour plus de détails.

0
efkan

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.
0
Ark Iv

[email protected]

J'ai utilisé Object.Keys pour obtenir le tableau de socket connecté. Puis, dans le même tableau, effectuez une itération avec la fonction map pour créer un nouveau tableau d'objets. 

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

Peut-être que cette réponse peut aider à obtenir un tableau d'identifiant de socket/nom d'utilisateur.

0
jvaldezb

Je ne sais pas si ça continue. Mais quelque chose comme ceci est ce que j’ai fini par utiliser (je garde un objet session sur chaque socket connecté, qui contient à son tour le nom d’utilisateur et d’autres informations:

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

Voici un moyen rapide de convertir le hachage des sockets connectés d'un espace de noms en un tableau utilisant des générateurs ES6 (s'applique à 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
})
0
Morgan