简体   繁体   中英

Count number of online users with nodeJS and Socket.io without duplicates

I'm having trouble displaying the correct amount of online users. A question similar to this have shown me that I can count the users this way:

var count = 0
  socket.on('connection', function(client) {
  count++;
  client.broadcast({count:count})
  client.on('disconnect', function(){
    count--;
  })
})

The issue I'm constantly running into with that method is that when a user happens to reload the page too quickly, the counter pulls in too much it can throw out.

在此处输入图片说明

As you can see, on the right side of the image, a user spammed the reload and it caught more users online than there actually is. (There was only one user on the server at this time)

My question is is there a better or more reliable way to count the exact amount users online without the extra 'virtual users', without using the users++ / users-- method?

If they're logging in as a user, then you should authenticate them to the socket. Use that authentication to see if they already have a session, and disconnect them decrementing the count, before you increment it again with the new session.

An example below. The clients objects stores the connected clients, with values being the sockets they're connected to.

var clients = {};
socket.on('connection', function(client) {
  //Authenticate the client (Using query string parameters, auth tokens, etc...), and return the userID if the user.
  var userId = authenticate(client);

  if ( !userId ) {
    //Bad authentication, disconnect them
    client.disconnect();
    return;
  }

  if (clients[userId]) {
    //They already have a session, disconnect
    clients[userId].disconnect();
    //Set updated session here
    clients[userId] = client;
  }
  client.broadcast({count: Object.keys(clients).length})
  client.on('disconnect', function(){
    delete clients[userId];
  })
})

Could do this pretty cleanly with the Observable pattern (using RxJS v5 here):

const { Observable } = require('rxjs')

const connections = Observable.fromEvent(socket, 'connection').mapTo(1)
const disconnections = Observable.fromEvent(socket, 'disconnect').mapTo(-1)

// emit 1 for connection, -1 for disconnection
Observable.merge(connections, disconnections)
  .scan((total, change) => total + change, 0) // emit total
  .subscribe(count => client.broadcast({ count }))

You can use Server Sent Events for this purpose really. Take a look at https://javascript.info/server-sent-events

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM