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.js
和Socket.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断开事件错误地为其他用户触发,然后再次连接