【问题标题】:Socket.IO Connected User CountSocket.IO 连接用户数
【发布时间】:2012-05-03 18:38:30
【问题描述】:

我终于让Socket.IO正常工作了,但是我遇到了一个奇怪的问题。

我不确定这是否是最好的方法,但我正在使用:

io.sockets.clients().length

这将返回连接到我的服务器的客户端数量。问题是在几次连接和断开用户之后,数量开始保持高于应有的水平。

例如,如果我连接并邀请我的朋友,数字会上升,这是正确的。但是当我们开始断开连接并重新连接时,数量并没有减少。

我在VMware Ubuntu 服务器上运行Node.jsSocket.IO 服务器。

为什么要这样或有更好的方法来找出有多少人连接到服务器?

【问题讨论】:

  • 我在我的项目中放弃了这个,转而使用 Sock.js,因为它有更好的文档并且有更多的开发活动。
  • 不再是 - 一年前的最后一次更新
  • 这些答案中的大多数都已经很老了。我添加了适用于最新版本 Socket.io 的 an answer(截至 2021 年 4 月,最新版本为 4.0.1)。在我看来,所有早于 2019 年的答案都应该尽可能更新。
  • 为什么是io.sockets.clients 而不是io.socket.clients(不是反问句)?

标签: node.js websocket socket.io


【解决方案1】:

为此有一个github issue。问题是,每当有人断开 socket.io 的连接时,都不会从数组中删除( splice ),而只是将值设置为“null”,因此实际上您的数组中有很多 null 值,这会使您的客户( ).length 比你在现实中的连接要大。

您必须管理一种不同的方式来计算您的客户,例如像

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

这是一个头脑嗡嗡声,为什么 socket.io 背后的人留下了这样的东西,但最好在 github 问题中解释,我将其作为链接发布!

【讨论】:

  • 谢谢,这是个好主意,我今晚试试。不能以某种方式拼接自己吗?这听起来很简单。
  • 嗯,这似乎有点困难,因为 github 上有很多关于这个的 cmets,socket.clients() 在脚本的其他地方使用,所以如果他们删除客户端并拼接它会损坏socket.io的其他部分
  • 在最新的socket.io@^2.0.3版本中使用这种方式,其他方式都行不通。
  • 我这样做了,我得到了 -600。 >__>
  • 参考this answer,2020年6月工作
【解决方案2】:

我正在使用 socket.io 0.9.10 和以下代码来确定套接字的数量:

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

不确定这个数字对各种边缘情况的反应有多准确,但直到现在它似乎是准确的:每个连接的浏览器都会增加这个数字,每个关闭的浏览器都会减少它。

【讨论】:

  • 不幸的是,这只适用于单个服务器进程。如果您有多个进程,每个进程都使用同一个 Redis 存储,这只会减少亲自见证断开连接的服务器进程的断开连接计数器。
【解决方案3】:

还可以看看:

io.sockets.manager.connected

这是一个干净的键值对列表(socket id 和连接状态?)

【讨论】:

  • 嗨@Gilnert-flamino,如果我在 2 个选项卡中启动相同的应用程序会怎样。我认为它显示了 2 个不同的连接。我将我的应用程序设计为一次登录的单个用户,这意味着如果用户在一个浏览器的多个选项卡中打开应用程序,我只需要一个计数(因为我必须显示在线用户数)用于登录用户。你有什么想法来实现这个目标吗?
  • 将多个选项卡视为一个客户端需要 sessions。会话数据在浏览器的所有窗口上的所有打开选项卡中都应该相同。 This small library 可以将会话数据提供给您的套接字连接。每个选项卡/窗口仍将获得其Socket 连接,但您可以测试每个Socket 是否已经在"connection" 事件中具有活动会话。 (即你不能通过计算Sockets来计算在线用户。)
【解决方案4】:

当您总是可以过滤数组时,为什么要使用(隐式全局)变量,它是通过调用 clients() 方法返回的。

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

编辑使用更短的语法

【讨论】:

  • 现在您可以使用io.sockets.clients().filter(c => !!c).length; 变得更短
【解决方案5】:

以防万一有人在使用 socket.io 1.0 版时访问此页面

您可以从中获取连接的客户端计数

socketIO.engine.clientsCount

需要一个答案,以上不适用于新版本的socket.io

【讨论】:

  • 这是否受到任何类型的错误的影响,例如 io.sockets.clients().length did/does?
  • 没有任何体验
  • 谢谢。 Socket.io 1.0 带来了许多可喜的变化,但大多数在线可用信息都与 socket.io 有关
【解决方案6】:

我目前正在使用 Socket.io v1.3.6 并且发现它有效。它会在用户连接和断开连接时给出准确的数字:

io.sockets.sockets.length

像这样:

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

【讨论】:

    【解决方案7】:

    我没有看到任何关于多核应用程序的提及,所以我只是要补充一点,因为我使用的是多核(集群),所以我无法在客户端始终获得正确数量的套接字,所以我最终将它们保存到我的 mongo 实例中,它非常一致和准确。使用这种方法,我可以通过浏览器查看我的套接字连接:)。

    猫鼬模式:

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

    用法:

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

    我有多少?

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

    注意我不喜欢使用空查询对象 ({}),所以我只使用 { "socket" : 1 } 作为虚拟对象

    【讨论】:

    • 我不确定我是否理解这个问题...此代码包含在一个集群中。我认为我不需要包含这部分内容
    • 我想知道如何使用集群。
    • 啊,我明白了……它们是内置在 Node.js 中的。入门文档在这里:nodejs.org/api/cluster.html。让几个集群与集群库一起使用实际上非常简单,但是一旦您开始在集群之间共享数据,它就会变得复杂。许多人最终使用像 nginx 这样的代理服务来管理集群之间的数据共享和像 redis 这样的会话存储。有很多例子。
    【解决方案8】:

    我在 1.3.7 版本中找到了解决方法。 有以下三种方法:

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

    希望这些可以帮助遇到同样问题的人。:)

    【讨论】:

    • 附言。 io 是 socket.io 的一个实例。就像在我的代码中一样:var io = require('socket.io')();
    • 第二种方法不再适用于 socket.io 1.4.5。我能找到的唯一类似的选择是Object.keys(io.sockets.sockets).length
    • 这些方法都不适用于最新的socket.io@^2.0.3版本。
    • @neelmeg 毕竟它有很大的突破性变化:)。
    【解决方案9】:

    我目前正在使用带有typeScript的socket v1.4.29,你可以通过这个找到连接的客户端数量

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

    【讨论】:

      【解决方案10】:

      使用 socket.io 版本 - 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
      });
      

      【讨论】:

      • 你能补充一点解释吗?你的回答可能对其他用户更有用。
      【解决方案11】:

      使用 socket.io 2.2.0 更容易:

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

      干杯

      【讨论】:

        【解决方案12】:

        使用命名空间的 Socket.IO v2.3.0 进行测试,我发现 4 个位置具有 clientCounts 属性(可能每次都是相同的 Server 对象):

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

        【讨论】:

          【解决方案13】:

          在阅读 Stack Overflow 帖子并多次查看 io.sockets.sockets 之后,我发现要获取已连接的套接字数量,您需要这样做:

          // io is the 'require'd socket.io module
          
          io.on("connection",function(socket){
              console.log("The number of connected sockets: "+socket.adapter.sids.size);
          });
          

          我已经在socket.io@4.0.1 上测试了这个非常简单的解决方案。

          【讨论】:

          • 是的,现在是时候了,stackoverflow 必须强制执行版本标签、代码标签并以该语言的统一格式格式化代码。这么多年过去了,现在世界变成了意大利面条。
          猜你喜欢
          • 2020-07-30
          • 1970-01-01
          • 1970-01-01
          • 2014-09-24
          • 1970-01-01
          • 2023-03-18
          • 2017-05-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多