59

I finally got Socket.IO to work properly, but I have encountered a strange problem.

I am not sure if this is the best way, but I am using:

io.sockets.clients().length

This returns the number of clients connected to my server. The problem is after a few connects and disconnects of users, the number starts to stay higher than it should be.

For instance, if I connect and ask my friends to, the number goes up which is correct. But when we start to disconnect and reconnect the number does not decrease.

I am running the Node.js and Socket.IO server on a VMware Ubuntu server.

Why is this or is there a better method for finding out how many people are connected to the server?

Salvatore
  • 10,815
  • 4
  • 31
  • 69
imperium2335
  • 23,402
  • 38
  • 111
  • 190
  • I have dropped this for my projects in favor of Sock.js as it has better documentation and has much more development activity. – imperium2335 Oct 08 '15 at 10:20
  • not any more - last update a year ago – danday74 Mar 22 '19 at 23:36
  • 1
    Most of these answers are pretty old. I added [an answer](https://stackoverflow.com/a/66994326/14469685) that is working for the latest version of Socket.io (as of April 2021 the latest is 4.0.1). Seems to me that all of the answers older than 2019 answers should get updated if possible. – Lakshya Raj Apr 12 '21 at 21:14
  • Why is it `io.sockets.clients` and not `io.socket.clients` (not a rhetorical question)? – Peter Mortensen Jun 02 '21 at 13:37

14 Answers14

73

Just in case someone gets to this page while using socket.io version 1.0

You can get the connected clients count from

socketIO.engine.clientsCount

Need an answer and the above did not work for new version of socket.io

Ahmad
  • 1,913
  • 13
  • 21
54

There is a github issue for this. The problem is that whenever someone disconnects socket.io doesn't delete ( splice ) from the array, but simply sets the value to "null", so in fact you have a lot of null values in your array, which make your clients().length bigger than the connections you have in reality.

You have to manage a different way for counting your clients, e.g. something like

socket.on('connect', function() { connectCounter++; });
socket.on('disconnect', function() { connectCounter--; });

It's a mind buzz, why the people behind socket.io have left the things like that, but it is better explain in the github issue, which I posted as a link!

Melki
  • 579
  • 2
  • 5
  • 26
drinchev
  • 19,201
  • 4
  • 67
  • 93
  • Thanks, that's a good idea I will try it out tonight. Couldn't one just splice themselves somehow? It sounds like a simple issue. – imperium2335 Apr 23 '12 at 07:40
  • 4
    Well it seems a bit difficult, since there are a lot of comments on github about this, the socket.clients() is used elsewhere in the script, so probably if they remove the client with splice it will damage other parts of socket.io – drinchev Apr 23 '12 at 07:44
  • 3
    Using this approach in the latest socket.io@^2.0.3 version, other methods din't work. – neelmeg Sep 30 '17 at 05:33
  • 3
    I did this and I got -600. >__> – nikk wong Aug 23 '18 at 23:28
  • refer to [this answer](https://stackoverflow.com/a/24425207/8235105) , worked on june 2020 – ego2509 Jul 27 '20 at 04:48
37

I have found the way to figure it out in version 1.3.7. There are three methods as follows:

  1. io.engine.clientsCount
  2. io.sockets.sockets.length
  3. Object.keys(io.sockets.connected).length

Hope these can help someone with the same issue.:)

Lordran
  • 649
  • 8
  • 15
13

with socket.io 2.2.0 it's easier :

io.on('connection', function (socket) {
    console.log( socket.client.conn.server.clientsCount + " users connected" );
});

cheers

rafa226
  • 536
  • 8
  • 17
11

Tested using Socket.IO v2.3.0 using namespace, I found 4 locations having the clientCounts property (it's probably the same Server object each time):

const socketio = require('socket.io');
const io = socketio(http_server);

const io_namespace = io.of('/foobar');

io_namespace.on('connection', function(socket)
{
    console.log(socket.conn.server.clientsCount);
    console.log(socket.server.engine.clientsCount);
    console.log(io.engine.clientsCount);
    console.log(io_namespace.server.engine.clientsCount);
});
Tristan CHARBONNIER
  • 1,119
  • 16
  • 12
8

Why use an (implicit global) variable when you could always filter the array, that is returned by calling the clients() method.

io.sockets.clients().filter(c => !!c).length;

EDIT use shorter syntax

line-o
  • 1,885
  • 3
  • 16
  • 33
8

Connected Users count in number with socket.io version - 1.3.7

const io = require("socket.io");

io.on('connection', (socket) => {
    console.log(io.sockets.server.httpServer._connections);  //output in number
    // or
    console.log(io.sockets.server.engine.clientsCount);  //output in number
});
Lakshya Raj
  • 1,669
  • 3
  • 10
  • 34
Pavani dasari
  • 81
  • 1
  • 3
  • Could you add a little bit of an explanation? Your answer could potentially be much more useful for other users then. – anothernode Aug 24 '18 at 11:34
  • This works for me. Declare `const count = io.sockets.server.engine.clientsCount;` in both `events`, `disconnect` and `connection` separately. Mostly it wont works because after `disconnected`, `count` can not be updated again for the current active connections. – Sabbir Sobhani Oct 03 '22 at 13:45
6

After spending quite some time reading Stack Overflow posts and looking at socket objects many times, I found that to get the number of sockets that are connected, you need to do:

// io is the 'require'd socket.io module

io.on("connection", function (socket) {
  console.log("The number of connected sockets: " + socket.adapter.sids.size);
});

I've tested this very simple solution on socket.io@4.0.1.

Lakshya Raj
  • 1,669
  • 3
  • 10
  • 34
  • 1
    Yes its about time now stackoverflow must enforce version tags, code tags and format the code in uniform format for that language. So many years have passed and now the world is in a version spagetti. – DragonFire Oct 27 '21 at 04:11
5

I am currently using Socket.io v1.3.6 and have found that this works. It gives an accurate number when users connect and when they disconnect:

io.sockets.sockets.length

Like so:

var io = require('socket.io').listen(server);
io.on('connection', function(socket) {
  console.log(io.sockets.sockets.length);
  socket.on('disconnect', function() {
    console.log(io.sockets.sockets.length);
  });
});
devtanc
  • 136
  • 1
  • 7
3

I'm using socket.io 0.9.10 and the following code to determine the number of sockets:

var socketIO =  require('socket.io').listen( .....
var numberOfSockets = Object.keys(socketIO.connected).length;

Not sure how accurate this number reacts to the various edge-cases, but 'til now it seems accurate: every browser connecting increases the number, every browser closed decreases it.

Anoop
  • 23,044
  • 10
  • 62
  • 76
dknaus
  • 1,133
  • 12
  • 16
  • 1
    Unfortunately, that only works with a single server process. If you have multiple processes each using the same Redis store, this only decreases the counter on disconnect for the server process that personally witnessed the disconnect. – Eric Mill Nov 22 '12 at 00:42
3

Also take a look into:

io.sockets.manager.connected

It's a clean list of key value pairs (socket id and connection state?)

Gilbert Flamino
  • 101
  • 2
  • 2
  • Hi @Gilnert-flamino, What If I have start same application in 2 tabs. I think it is showing 2 different connection. I have designed my application as single user logged in at a time, means If user open application in many tabs of one browser, I want just one count (because I have to show No. Of Online users) for logged in user. Do you have any idea to achieve this? – Manish Sapkal May 12 '14 at 11:08
  • 1
    Treating multiple tabs as one client requires *[sessions](http://expressjs-book.com/forums/topic/express-js-sessions-a-detailed-tutorial/)*. Session data should be the same across all open tabs on all windows of a browser. [This small library](https://github.com/wcamarao/session.socket.io) can give session data to your socket connections. Each tab/window will still get its `Socket` connection, but you can test if each `Socket` already has an active session in the `"connection"` event. (i.e. You cannot count online users by counting `Sockets`.) – kdbanman Jun 26 '14 at 04:54
1

I don't see any mention of multi core apps so I'm just gonna add that since I am using multiple cores ( clusters ) I wasn't able to get the right number of sockets consistently on the client side, so I ended up saving them to my mongo instance and it is quite consistent and accurate. With this approach I can view my socket connections in style via the browser :).

Mongoose schema :

var socketSchema = mongoose.Schema({
        socket : Number
});

Usage:

//reset to 0 when the app starts ( just in case )
SocketModel.find({ "socket" : 1 } , function(err, deadSockets ) {
    if (err){
        console.log( err );
    }
    else{
        for( var i = 0 ; i < deadSockets.length ; i++ ){
            deadSockets[i].remove();                
        }
    }
});

io.on('connection', function( socket ) {
    //I found I needed to make sure I had a socket object to get proper counts consistantly
    if( socket ){
        var socketEntry = new SocketModel({ "socket" : 1 });
        socketEntry.save( function(err ){
            if (err){
                console.log( err );
            }
            else{
        
            }
        });
    }
    //On Disconnect
    socket.on('disconnect', function() {
        SocketModel.findOne({ "socket" : 1} , function(err, deadSocket ) {
            if (err){
                console.log( err );
            }
            else{
                deadSocket.remove();
            }
        }); 
    });
});

How many do I have ?

SocketModel.count({ "socket" : 1 } , function(err, count ) {
    if (err){
        console.log(err);
    }
    else{
        var term = "sockets";
        if( count == 1 ) term = "socket";
        console.log("Current Load: " , count , term );
    }
}); 

NOTE I don't like using empty query objects ( {} ) so I just used { "socket" : 1 } as a dummy instead

baldr
  • 2,891
  • 11
  • 43
  • 61
Squivo
  • 917
  • 1
  • 10
  • 21
  • I'm not sure I understand the question... this code is wrapped inside a cluster. I didn't think I needed to include that part of it – Squivo Oct 01 '15 at 15:40
  • I'd like to know how to use clusters. – imperium2335 Oct 02 '15 at 06:17
  • Ahh I see ... well they are built into Node.js. The documentation to get started is here: https://nodejs.org/api/cluster.html. Getting a few clusters going with the cluster library is actually quite simple, but once you get into sharing data between clusters it gets complicated. Many folks end up using proxy services like nginx to manage sharing data between clusters and a session store like redis. There's many examples. – Squivo Oct 02 '15 at 15:10
1

I am currently using socket v1.4.29 with typeScript, you can find the number of clients connected by using this

 io.sockets.on('connection', function(socket) {
 var clients = socket.client.conn.emit.length;
 console.log("clients: " + clients);
 });
parinita
  • 11
  • 2
0

To return the total number of connected clients

console.log(io.engine.clientsCount)
  • What new information does this answer provide? Isn't this the same solution suggested in [this post](https://stackoverflow.com/a/27408752/14469685), which is currently the highest scoring? – Lakshya Raj Nov 12 '22 at 03:13