Node.js Socket.io 页面刷新多个连接 [英] Node.js Socket.io page refresh multiple connections

查看:27
本文介绍了Node.js Socket.io 页面刷新多个连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 socket.io (1.5) 的简单 node.js 服务器代码:

var io = require('socket.io').listen(8080);io.on('连接', 函数(socket) {console.log('%s 套接字已连接', io.engine.clientsCount);socket.on('断开', 函数() {console.log("断开连接:", socket.id);});});

如果我运行此代码并多次按 F5,在某些情况下,会在旧连接断开之前创建新连接.一段时间后,我认为是心跳超时,所有连接都将关闭.查看结果:

 2个socket连接3个插座连接4个插座连接5个插座连接6个插座连接7个插座连接8个插座连接9个插座连接10个插座连接11个插座连接断开连接:0h_9pkbAaE3ftKT9AAAL11个插座连接12个插座连接13个插座连接14个插座连接断开连接:oB4HQRCOY1UIvvZkAAAP14个插座连接15个插座连接断开连接:LiIN0oDVoqbePgxFAAAR15个插座连接16个插座连接17个插座连接18个插座连接断开连接:zxvk-uhWABHzmu1uAAAV18个插座连接19个插座连接20个插座连接断开连接:FlboxgTzcjf6ScffAAAY20个插座连接21个插座连接断开连接:9UGXbnzukfGX_UtWAAAa21个插座连接断开连接:pAfXOez6RocKZdoZAAAb21个插座连接断开连接:DIhTyVgG2LYBawaiAAAc21个插座连接断开连接:W4XOc1iRymfTE2U0AAAd21个插座连接断开连接:WZzegGPcoGDNLRTGAAAe21个插座连接22个插座连接断开连接:KVR3-fYH0cz77BmgAAAC断开连接:ANQknhnxr4l-OauIAAAD断开连接:KZE5orNx6u9MbOArAAAE断开连接:TS6LL3asXrcznfcPAAAF断开连接:SVNxS3I7KqecdqKhAAAG断开连接:IE2WE5Y0PJzvxgBfAAAH断开连接:v69bdJav9PjpThBGAAAI断开连接:mJKT1ggfOOTshZKgAAAJ断开连接:YlycVjdcWe0emCAcAAAK断开连接:MoIDJSzP_L-1RUwuAAAM断开连接: wAl0x5qwCkrnDDYQAAAN断开连接:eiTlPEk2Hx_X-L-fAAAO断开连接:KgkrXxzG_EpXOsPTAAAQ断开连接:Lvf3kK-6XXEbu3NWAAAS断开连接:-hOoGdYOIvVK04K_AAAT断开连接:3EUmaAYpK-U3Ss9tAAAU断开连接:HQ6M98FebtKlU3OfAAAW断开连接:OwgrbRBYbS4j84nmAAAX断开连接:yN8FZAP4RjUNl2MeAAAZ断开连接:K9IFTjlgAWzdNfpUAAAf

我的问题是:这是一个 Bug 还是 socket.io 的正常行为?如何防止连接泛滥,只需按 F5?

最好的问候马克

解决方案

我制作了自己的测试应用程序,并且能够弄清楚发生了什么.

如果你多次按 F5 相当快,它会暂时在 Chrome 中积累一些额外的 socket.io 连接,但在相对较短的时间内(可能几分钟),它恢复并且连接的套接字总数回到1.

经过进一步测试,我发现这不是浏览器问题.这是 socket.io 如何启动 socket.io 连接的问题.如果您在客户端替换它:

var socket = io();

这样:

var socket = io({transsports: ['websocket'], upgrade: false});

这迫使 socket.io 只使用 webSocket 而从不使用 HTTP 轮询,然后问题就消失了.

所以,问题是因为 socket.io 的默认行为是从 socket.io 连接的 http 轮询版本开始.交换少量数据后,socket.io 将尝试切换到真正的 webSocket.如果那个真正的 webSocket 有效,那么它将停止使用 http 轮询连接.

但是,如果你在轮询和真正的 webSocket 之间的这个转换过程中按下 F5,那么 socket.io 还没有持久连接知道它刚刚与之通信的网页现在已经消失了.因此,它所能做的就是在一段时间后确定不再有来自该网页的任何传入通信,因此它应该清除它的 socket.io 连接(当您按 F5 时它处于轮询模式).

但是,如果您使用上述客户端代码关闭初始轮询模式,那么它只会使用真正的 webSocket(从不使用模拟轮询模式),并且当您按 F5 时,浏览器非常擅长清理 webSocket所以服务器要么没有完成建立它的 socket.io 连接(在这种情况下还没有连接暂时孤立)或者它已经转换为 webSocket(浏览器将在 F5 上干净地关闭它).

所以,这是socket.io启动的http轮询模式的设计限制.由于在该模式下没有连续连接,因此当该页面被F5替换时浏览器不会立即通知,因此服务器无法知道客户端刚刚消失.但是,如果您跳过 http 轮询模式并从真正的 webSocket 开始,则没有这样的时间窗口,那里有 socket.io 连接,但没有真正的 webSocket,因此浏览器总是会立即通知服务器关闭 webSocket页面消失时的连接.

i have this simple node.js Servercode using socket.io (1.5):

var io = require('socket.io').listen(8080);

io.on('connection', function(socket) {

    console.log(' %s sockets connected', io.engine.clientsCount);

    socket.on('disconnect', function() {
        console.log("disconnect: ", socket.id);
    });
});

If i run this code und press F5 several times, in some cases new connection is created, before the old one is disconnected. After some time, i think its the Heartbeat Timout, all the connections will be closed. See the result:

 2 sockets connected
 3 sockets connected
 4 sockets connected
 5 sockets connected
 6 sockets connected
 7 sockets connected
 8 sockets connected
 9 sockets connected
 10 sockets connected
 11 sockets connected
disconnect:  0h_9pkbAaE3ftKT9AAAL
 11 sockets connected
 12 sockets connected
 13 sockets connected
 14 sockets connected
disconnect:  oB4HQRCOY1UIvvZkAAAP
 14 sockets connected
 15 sockets connected
disconnect:  LiIN0oDVoqbePgxFAAAR
 15 sockets connected
 16 sockets connected
 17 sockets connected
 18 sockets connected
disconnect:  zxvk-uhWABHzmu1uAAAV
 18 sockets connected
 19 sockets connected
 20 sockets connected
disconnect:  FlboxgTzcjf6ScffAAAY
 20 sockets connected
 21 sockets connected
disconnect:  9UGXbnzukfGX_UtWAAAa
 21 sockets connected
disconnect:  pAfXOEz6RocKZdoZAAAb
 21 sockets connected
disconnect:  DIhTyVgG2LYBawaiAAAc
 21 sockets connected
disconnect:  W4XOc1iRymfTE2U0AAAd
 21 sockets connected
disconnect:  WZzegGPcoGDNLRTGAAAe
 21 sockets connected
 22 sockets connected
disconnect:  KVR3-fYH0cz77BmgAAAC
disconnect:  ANQknhnxr4l-OAuIAAAD
disconnect:  KZE5orNx6u9MbOArAAAE
disconnect:  TS6LL3asXrcznfcPAAAF
disconnect:  SVNxS3I7KqecdqKhAAAG
disconnect:  IE2WE5Y0PJzvxgBfAAAH
disconnect:  v69bdJav9PjpThBGAAAI
disconnect:  mJKT1ggfOOTshZKgAAAJ
disconnect:  YlycVjdcWe0emCAcAAAK
disconnect:  MoIDJSzP_L-1RUwuAAAM
disconnect:  wAl0x5qwCkrnDDYQAAAN
disconnect:  eiTlPEk2Hx_X-L-fAAAO
disconnect:  KgkrXxzG_EpXOsPTAAAQ
disconnect:  Lvf3kK-6XXEbu3NWAAAS
disconnect:  -hOoGdYOIvVK04K_AAAT
disconnect:  3EUmaAYpK-U3Ss9tAAAU
disconnect:  HQ6M98FebtKlU3OfAAAW
disconnect:  OwgrbRBYbS4j84nmAAAX
disconnect:  yN8FZAP4RjUNl2MeAAAZ
disconnect:  K9IFTjlgAWzdNfpUAAAf

My Question is: Is this a Bug or is this the normal behavior of socket.io? How can i prevent the connection flooding, simple pressing F5?

Best Regards Marc

解决方案

I made my own test app and was able to figure out what is going on.

If you hit F5 quite fast multiple times, It does temporarily accumulate some extra socket.io connections in Chrome, but within a relatively short time (maybe a few minutes), it recovers and the total count of connected sockets is back to 1.

After further testing, I discovered that this is not a browser issue. This is an issue with how socket.io starts a socket.io connection. If you replace this in the client:

var socket = io();

with this:

var socket = io({transports: ['websocket'], upgrade: false});

which forces socket.io to ONLY use a webSocket and never use HTTP polling, then the problem disappears.

So, the issue is because the default behavior for socket.io is to start with an http polling version of a socket.io connection. After a little data is exchanged, socket.io will then attempt to switch over to a real webSocket. If that real webSocket works, then it will stop using the http polling connection.

But, if you hit an F5 in the middle of this transition between polling and a real webSocket, there is no persistent connection yet for socket.io to know that the web page it was just communicating with is now gone. So, all it can do is to figure out some time later that there is no longer any incoming communication from that web page and thus it should clear up it's socket.io connection (it was in polling mode when you hit F5).

But, if you turn off that initial polling mode with the above client code, then it only ever uses a real webSocket (never uses the simulated polling mode) and the browsers are very good at cleaning up the webSocket when you hit F5 so the server either hasn't finished establishing it's socket.io connection (in which case there's no connection yet to get temporarily orphaned) or it's already converted over to a webSocket (and the browser will cleanly close that on the F5).

So, this is a design limitation of the http polling mode that socket.io starts in. Since there is no continuous connection when in that mode, there is no immediately notification by the browser when that page is replaced with F5 and thus the server has no way of knowing that the client just disappeared. But, if you skip the http polling mode and start with a real webSocket, then there is no such window of time where there's a socket.io connection, but no real webSocket and thus the server is always told immediately by the browser closing the webSocket connection when the page goes away.

这篇关于Node.js Socket.io 页面刷新多个连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆