Socket.IO 连接用户数

Posted

技术标签:

【中文标题】Socket.IO 连接用户数【英文标题】:Socket.IO Connected User Count 【发布时间】: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(不是反问句)? 【参考方案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 版本中找到了解决方法。 有以下三种方法:

    io.engine.clientsCount io.sockets.sockets.length 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 上测试了这个非常简单的解决方案。

【讨论】:

是的,现在是时候了,*** 必须强制执行版本标签、代码标签并以该语言的统一格式格式化代码。这么多年过去了,现在世界变成了意大利面条。

以上是关于Socket.IO 连接用户数的主要内容,如果未能解决你的问题,请参考以下文章

刷新时Socket.io断开连接?

Socket.io断开事件错误地为其他用户触发,然后再次连接

即使用户转到网站内的不同页面,socket.io 连接是不是仍然存在?

Socket.io 中的连接不稳定

Socket.io 会话管理?

一次与两个用户随机聊天(Socket.io)