200

I'm trying to get a list of all the sockets/clients that are currently connected.

io.sockets does not return an array, unfortunately.

I know I could keep my own list using an array, but I don't think this is an optimal solution for two reasons:

  1. Redundancy. Socket.IO already keeps a copy of this list.

  2. Socket.IO provides method to set arbitrary field values for clients (i.e: socket.set('nickname', 'superman')), so I'd need to keep up with these changes if I were to maintain my own list.

What should I do?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andy Hin
  • 30,345
  • 42
  • 99
  • 142
  • Can't you just convert io.sockets to an array? – mak Jul 03 '11 at 17:15
  • No, io.sockets is actually a complex object and does not simply store a list of socket objects. For now, I am going to manage my own list of user objects and avoid using the socket.set() function. – Andy Hin Jul 03 '11 at 17:33
  • 2
    In 0.7.6 io.sockets.sockets is a simple hash object id => socket – mak Jul 03 '11 at 17:34
  • 1
    I noticed that, but it is acting strange (does not seem like standard socket objects). For example I tried: http://pastebin.com/fxuzVckS but it is saying the socket object does not contain a 'get' method. – Andy Hin Jul 03 '11 at 17:59
  • 3
    `socket` is id, `io.sockets.sockets[socket]` is the socket. – mak Jul 03 '11 at 18:08
  • Right. That makes sense. I tried the following: http://pastebin.com/kJcHzpvV and it seems like nickname is returning null. What am I doing wrong? – Andy Hin Jul 03 '11 at 18:17
  • 2
    First argument is `err` and if you're using memory store it's always `null`. `.get('nickname', function(err, nickname) { ... })` – mak Jul 03 '11 at 18:44

35 Answers35

194

In Socket.IO 0.7 you have a clients method on the namespaces. This returns an array of all connected sockets.

API for no namespace:

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

For a namespace

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

Note: This solution only works with a version prior to 1.0

From 1.x and above, please refer to getting how many people are in a chat room in socket.io.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3rdEden
  • 4,388
  • 1
  • 20
  • 18
  • 3
    I think they've dropped the clients method in 1.0... just checking that out at the moment... – marksyzm Apr 07 '14 at 14:08
  • 7
    They dropped nearly everything in 1.0 as it's a complete rewrite. But as 1.0 has been unreleased for years. In 1.0 you have to use the `connected` object of the namespace. – 3rdEden Apr 08 '14 at 13:17
  • 6
    @3rdEden, what is the syntax for using the connected object of namespace ? `var clients = io.sockets.connected();` obviously doesn't work. Thanks – Kaya Toast Jul 05 '14 at 04:44
  • 5
    From 1.x and above: http://stackoverflow.com/questions/9352549/getting-how-many-people-are-in-a-chat-room-in-socket-io#24425207 – Musa Haidari Jun 07 '16 at 05:54
  • 1
    TypeError: fn.bind is not a function – Iman Marashi Apr 25 '20 at 07:00
  • Note that you identify individual socket devices with property ```socket.id```, I usually store all ids in an array as new devices connects, length of that array gives the number of clients. The benefit of this is later you can identify if new connected device already exists in that array or not. Similarly you can remove devices from array when 'disconnect' event is called. – krupesh Anadkat Jun 01 '20 at 18:19
  • The current answer to this question is: io.sockets.sockets.size – Joshu Jun 20 '22 at 18:02
106

Socket.IO 1.4

Object.keys(io.sockets.sockets); gives you all the connected sockets.

Socket.IO 1.0

As of Socket.IO 1.0, the actual accepted answer isn't valid any more.

So I made a small function that I use as a temporary fix:

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

The API for no namespace becomes:

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

The API for a namespace becomes:

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

Also see this related question, in which I give a function that returns the sockets for a given room.

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

The API for no namespace:

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

For a namespace

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

Note: Since it seems the Socket.IO API is prone to breaking, and some solution rely on implementation details, it could be a matter of tracking the clients yourself:

var clients = [];

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

    client.on('disconnect', function() {
        clients.splice(clients.indexOf(client), 1);
    });
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nha
  • 17,623
  • 13
  • 87
  • 133
  • 1
    @TylerScott Me too, especially given that this is not covered in their migration guide (unless I am missing something). http://socket.io/docs/migrating-from-0-9/ – nha Jun 19 '14 at 15:11
  • @nha, this doesn't work for me but returns an array of Integers, like 0, 1 and 2 etc instead of an array of sockets. Any ideas? – ThePixelPony Sep 20 '14 at 07:09
  • how about for multiple node? because I using multiple node with redis store – John Nguyen Mar 31 '15 at 09:58
  • 3
    @nha you answer is exactly, but it not working for multiple node with redis store server. from 1 node process, you can not check socket connected or not by using ns.connected[id] – John Nguyen Apr 01 '15 at 09:52
46

After Socket.IO 1.0, we cannot use

io.sockets.clients();

or

io.sockets.clients('room');

any more.

Instead you can use the following:

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
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
salihcenap
  • 1,927
  • 22
  • 25
39

Using Socket.IO 1.x:

Get an array of the connected clients:

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

Get the number of connected clients:

io.engine.clientsCount // => 2
io.eio.clientsCount    // => 2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joseph Dykstra
  • 1,416
  • 1
  • 15
  • 17
33

It is very simple in Socket.IO 1.3:

io.sockets.sockets - is an array containing the connected socket objects.

If you stored the username in each socket, you can do:

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

Boom. You have the names of all connected users.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
or29544
  • 608
  • 5
  • 7
23

I've gone through this pain today. Socket.IO would be much better if they could make a proper documentation for their API.

Anyway, I tried to look into io.sockets and found a number of options we can use:

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

Also, do note that when using socket.io with namespace, the above methods will break since io.sockets becomes an array instead of an object. To resolve, just replace io.sockets by io (i.e., io.sockets.connected becomes io.connected, io.sockets.adapter.rooms becomes io.adapter.rooms...)

It was tested on Socket.IO 1.3.5.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thanh Nguyen
  • 340
  • 3
  • 8
  • 1
    @Зелёный It will work if you're not using namespace. If you're using namespace, change to io.server.eio.clientsCount – Thanh Nguyen Dec 10 '15 at 07:55
23

Update Socket.IO v4.0+ (last checked Nov 6 2022)

I've tried all of the other answers... None of them worked, except this:

The easiest way to get all the connected sockets is through:

await io.fetchSockets()

It returns an array of all connected sockets

Documentation

// Return all Socket instances
const sockets = await io.fetchSockets();

// Return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in("room1").fetchSockets();

// Return all Socket instances in the "room1" room of the "admin" namespace
const sockets = await io.of("/admin").in("room1").fetchSockets();

// This also works with a single socket ID
const sockets = await io.in(theSocketId).fetchSockets();

Example usages

// With an async function

 const sockets = await io.fetchSockets()
 sockets.forEach(socket => {
    // Do something
 });
// Without an async function

io.fetchSockets()
.then((sockets) => {
  sockets.forEach((socket) => {
    // Do something
  })
})
.catch(console.log)
Coder Gautam YT
  • 1,044
  • 7
  • 20
20

Version 2.x

In version 2.x you specify the namespace/room/node you are querying against.

As with broadcasting, the default is all clients from the default namespace ('/'):

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

Gets a list of client IDs connected to specific namespace (across all nodes if applicable).

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

An example to get all clients in namespace's room:

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

This is from the official documentation: Socket.IO Server-API

Josh Weston
  • 1,632
  • 22
  • 23
  • 1
    is there a way to view all socket *objects*? for example, if i add a `socket.username` property to each socket on connecting, is there a way i can view all of these socket objects (including the custom properties i add to each socket)? (for reference, i am currently using a global object variable to store additional socket information when a client connects - so not asking how to set that up - just interested in knowing if there is a way to view all socket objects by 'default'). – user1063287 Jun 07 '19 at 00:14
  • 1
    hmm, [per this answer](https://stackoverflow.com/a/38039911), i think you can see all connected sockets with `console.log(io.sockets.connected)` - it seems to be an object where each property value is a "socket object" which contains these properties `nsp`, `server`, `adaptor`, `id` ( a string), `client`, `conn`, `rooms`, `acks`, `connected`, `disconnected`, `handshake`, `fns`, `flags`, `_rooms`, `_events`, `_eventsCount` and finally `username` which is the custom property i add to each socket on connection. – user1063287 Jun 07 '19 at 00:30
  • What is "+2.0"? After 2.0 (not including 2.0)? – Peter Mortensen Aug 30 '22 at 10:27
  • Edited to specify as v2.x. Also edited broken link to Socket.IO's v2.x Server API documentation. – Josh Weston Aug 31 '22 at 06:43
17

I think we can access the socket object from the server, and you can assign the nickname, and point its socket 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");
    });    
});

On disconnect please remove the nickname from io.sockets.sockets.

franzlorenzon
  • 5,845
  • 6
  • 36
  • 58
sunil n jose
  • 179
  • 1
  • 2
  • what is the purpose of 'client.on'? Can you use your code like this (only accepting data from 1 socket)?: io.sockets.sockets[sock_id].on('newmessage', function (data) { console.log(data) }); – The Hawk Nov 27 '12 at 22:34
9

This is the best way to access it in Socket.IO 1.3:

Object.keys(socket.adapter.rooms[room_id])
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ksloan
  • 1,482
  • 1
  • 13
  • 19
  • please let me share this example , `var room = io.sockets.adapter.rooms[room_id];` `var connections = _.map(Object.keys(room), function(socketId){ return (io.sockets.connected[socketId].connected == true) });` – Hany Alsamman Nov 17 '15 at 11:48
  • *Why* is it the best way? What makes it the best way? Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/28532584/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Aug 30 '22 at 10:07
8

Version 4.0 and later (2021)

None of the answers worked for me. I will spare you the pain. Their API and documentation have changed greatly since 1.0 onward.

Server API: all available options

But you need to dig deeper 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;

});

UPDATE 2023 - Get All Connected Users

I want to add to this answer by showing you how you can attach the userid to the socketid to create persistence if you need it to use it in a project(ie: private messaging).

client.js (client-side)

/***
*
*
* getConnectedUsers
*
*
*
*/
function getConnectedUsers(){
/**
*
*
* STEP 1
* GET
*
*
*/
//
var userID = localStorage.getItem('userid');//this typically would be the unique id from your database. Set this variable at login()
//set-username
socket.auth = { userID };
//console.log(socket.auth);
//
//get-connected-socket-users
socket.emit('get-connected-socket-users',{
userid:userID
});
}
/**
*
*
* STEP 2
* SET
* use this for instant communication
*
*/
socket.on('connected-socket-users',function(data){

//console.log(data);
var connectedUsers = JSON.stringify(data);

localStorage.setItem('connectedUsers',connectedUsers);
//console.log(localStorage.getItem('connectedUsers'));


});

server.js (server side)

/**
* 
* 
* GET ALL CONNECTED USERS
* 
* 
*/
socket.on('get-connected-socket-users',function(data){
//
//variables
var userid = data.userid;
socket.username = userid;
//console.log(io.sockets);
//console.log(userid);
/**
* 
* GET ALL CONNECTED USERS
* 
*/
const users = [];
var clients = io.sockets;
clients.sockets.forEach(function(data,counter){

users.push({
userSocketID: data.id,
username: data.username,
});

});


//console.log(users);
//var handle = 
setInterval(function(){

socket.emit("connected-socket-users", users);

}, 3000);


// When you want to cancel it:
//clearInterval(handle);
//handle = 0; // I just do this so I know I've cleared the interval


});
Grogu
  • 2,097
  • 15
  • 36
5

Socket.IO 1.4.4

Sample code for you.

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;
    });
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
5

In Socket.IO 1.4

To get the array of all connected users:

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

To get the count of all clients:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KIA
  • 182
  • 2
  • 9
5

For anyone that just wants a count of the connected clients, I believe this will do it:

io.sockets.manager.server.connections

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
crickeys
  • 3,075
  • 3
  • 26
  • 27
  • isnt the connected clients count, tested. (bit more) – e382df99a7950919789725ceeec126 Mar 16 '12 at 00:25
  • 5
    in order to get an accurate count use `io.sockets.clients().length` – ivoputzer Apr 07 '13 at 12:35
  • 2
    Currently both `io.sockets.manager.server.connections` and `io.sockets.clients().length` dont work. This worked for me - For count only - `io.engine.clientsCount` and for the list of clients - `io.engine.clientsCount`. Since it has stayed this way for over 3 years. Seems like a reliable way to get the connection info. (Based on Joseph Dykstra's answer) – Aswin Ramakrishnan Jun 13 '17 at 03:35
3

As of Socket.IO 1.5, note the change from indexOf which appears to de deprecated, and replaced by 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;
}

For Socket.IO version 2.0.3, the following code works:

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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MoleIsKing
  • 131
  • 5
3

Socket.IO 3.0

io.in('room1').sockets.sockets.forEach((socket, key) => {
    console.log(socket);
})

It gets all socket instances in room1.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Atila Pehlivan
  • 171
  • 2
  • 4
2

In Socket.IO 1.3, I've accomplished this in two lines:

var usersSocketIds = Object.keys(chat.adapter.rooms['room name']);
var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] })
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Coelhone
  • 310
  • 1
  • 11
2

Socket.io 1.7.3 or later:

function getConnectedList ()
{
    let list = []
    
    for (let client in io.sockets.connected)
    {
        list.push(client)
    }
    
    return list
}

console.log(getConnectedList())

// returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexandre Daubricourt
  • 3,323
  • 1
  • 34
  • 33
2

For version 2.3, this works and it will get you the socket too. It seems to me that socketIo is changing too fast and to much with to little readable documentation after using it for a while.

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

Still this does not feel right, as I have always this feeling with Socket.IO somehow.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

For cluster mode, using Redis adapter:

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

});

As each socket is itself a room, one can find whether a socket exist using the same.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Anuj Nautiyal
  • 599
  • 1
  • 4
  • 11
2

namespace.allSockets()

It returns a Promise<Set<SocketId>>.

io.allSockets(): All connected socket ids in the main namespace

io.in('room').allSockets(): All connected ids in the 'room'

io.of('/namespace').allSockets(): All connected ids in '/namespace' (you can also combine this with rooms)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
M. Emre Yalçın
  • 608
  • 1
  • 7
  • 10
  • 1
    This works in both Socket.IO v3.x and v4.x. If you want to get the actual Socket objects from the Set of IDs received from `allSockets()` you can use `io.of('/namespace').sockets` to get a Map of all Socket instances connected to a namespace so `io.of('/namespace').sockets.get(socketId)` gets the Socket instance matching the ID. – Samuli Asmala Mar 26 '21 at 07:59
2

io.sockets.sockets.keys()

This helps me.

g721
  • 21
  • 1
  • Can you elaborate? How does this get *"a list of all the sockets/clients that are currently connected"*? Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/68149143/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Aug 30 '22 at 10:42
2

To get a list of socket id's, you can do:

[...io.sockets.sockets].map(s => s[0]);

To get the socket object, do:

[...io.sockets.sockets].map(s => s[1]);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

I saw a lot of good answers here and many were quite useful, but not quite what I needed. I am using sockets for a pubsub feature in which an interested client can listen to any changes in a given record.

My specific issue was that the same socket was joining the same room several times. The solution to this was to check if the socket had the room inside its rooms property already.

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");
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gus Ortiz
  • 652
  • 3
  • 9
  • I think it's possible to avoid that 'if' statement, if you make client join the room upon socket connection. – Chayemor Nov 25 '15 at 09:29
  • Where does myObj come from? How did you arrive at that value? – Michael Draper Dec 10 '15 at 05:05
  • @MikeDraper myObject is the record in a database that acts as a channel. What this solves is the case where you want all your clients to be updated whenever a change in the database happens, for instance a user updates its name and all connected clients get an update. So I create a room for that instance id, given that it is unique (BSON). It is a very specific value for my use case, so I'm sorry If I caused any confusion. Let me know if you need help :) – Gus Ortiz Dec 16 '15 at 22:41
  • @JMR due to the nature of my app it happened that a socket got subscribed more than once, that's why I had to add that check. – Gus Ortiz Feb 11 '16 at 16:00
1

This is the simplest way in Socket.IO 1.0 or later, if you are not using namespaces or rooms.

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

This looks at the default namespace and determines the length of the sockets array, without needing to use Object.keys().

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
suncannon
  • 194
  • 1
  • 9
1

As of version 1.5.1, I'm able to access all the sockets in a namespace with:

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

For some reason, they're using a plain object instead of an array to store the socket IDs.

rppc
  • 68
  • 4
1

If the project has a socket.io cluster this means the socket.io-redis adapter is being used.

If the case is like the above, getting the all connected sockets id processes must be applied via the socket.io-redis adapter. The examples below might be used for this;

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

Please visit socket.io-redis github page for more details.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
efkan
  • 12,991
  • 6
  • 73
  • 106
1

Socket.IO 4.x

const socketsOnDefaultNamespace = io.of('/').sockets.size;
console.log("Number of clients connected: ", socketsOnDefaultNamespace);

const socketsInARoomInSomeNamespace = io
  .of('/someNamespace')
  .in('/someRoomname')
  .fetchSockets()
  .then((room) => {
      console.log("clients in this room: ", room.length);
    });

You can read more in the documentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Isaac Pak
  • 4,467
  • 3
  • 42
  • 48
1

I believe you can access this from the socket's manager property:

var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dan Steele
  • 1,644
  • 3
  • 13
  • 13
  • 3rdEden's answer didn't work for me as there are issues with the array returning disconnected clients, which throws off the count. Object.keys(io.manager.open).length turned out to be the most reliable count in my experience. io.of('/namespace').manager.open if you're using namespaces. – Wes Johnson Apr 15 '12 at 22:19
0

Here is a quick way to convert the hash of connected sockets from a namespace into an array using ES6 generators (applies to 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
})
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
morganney
  • 6,566
  • 1
  • 24
  • 35
0

But something like this is what I ended up using (I keep a session object on each connected socket, which in turn contains the username and other information:

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return io.sockets.connected[socketId].session.username;
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
diazd2
  • 1
0

Socket.IO 1.7.3

I used Object.Keys to get the array of the connected socket. Then in the same array iterate with the map function to build a new array of objects:

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

This should help to get the socket id/username array.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jvaldezb
  • 44
  • 1
  • 7
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.
user1063287
  • 10,265
  • 25
  • 122
  • 218
Ark Iv
  • 7
  • 1
  • 1
  • 2
    It would be good if you could add some context why 'This is the best way' and how your answer adds anything to all of the many answers above. Code is something, but an answer should also have some explanation. As you can see there are many other answers to this question. Your answer must brings something more to the subject, otherwise, it is redundant. – Nathan Ripert Oct 02 '18 at 11:05
  • With `socket.io 2.1.1 `, I get `TypeError: clients.map is not a function` and although it looks promising, i'm not entirely sure what the above example will achieve - i was hoping it would automagically create an array of client objects with usernames included :). – user1063287 Nov 22 '18 at 13:07
  • What do you mean by *"v.10"*? I don't think version 10 has been released yet. Do you mean *"v. 1.0"*? – Peter Mortensen Aug 30 '22 at 10:45
0

For Socket.IO version 4.0.0

On the server side, to list some property of all active sockets, I use this:

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

Explanation:

sck=io.sockets.sockets is a Map object.

The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object.

en=mapIter.next().value?.[0] gets the key - the first element of a pair.

If there is no more to iterate, en becomes undefined and this breaks the while loop.

Example:

My sockets have property 'playerName', and I want to list names of all active players in all rooms. To do that, I simply call the function:

listSocketsProperty('playerName')

and get something like this in the console:

John
Peter
Zoran
etc.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zoran
  • 21
  • 1
  • 2
0

Easy reference for Socket.IO v4

socket.server.eio.clients
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Crispy
  • 23
  • 4
  • Can you elaborate? E.g., what is it supposed to do? How does this get *"a list of all the sockets/clients that are currently connected"*? Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/69754060/edit), not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Aug 30 '22 at 10:59
  • Hi @PeterMortensen. This response is more than a year old, and this does some what answer the question. It is a way to get the current clients connected to the socket. Thanks. – Crispy Oct 24 '22 at 05:07