简体   繁体   English

使用 nodeJS 和 Socket.io 计算在线用户数,无重复

[英]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?我的问题是有没有更好或更可靠的方法来计算在线用户的确切数量,而无需额外的“虚拟用户”,而无需使用users++ / users--方法?

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. clients对象存储连接的客户端,值是它们连接的套接字。

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):可以使用 Observable 模式非常干净地完成此操作(此处使用 RxJS v5):

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看看https://javascript.info/server-sent-events

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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