简体   繁体   English

Node.js Socket.io 页面刷新多个连接

[英]Node.js Socket.io page refresh multiple connections

i have this simple node.js Servercode using socket.io (1.5):我有这个使用 socket.io (1.5) 的简单 node.js 服务器代码:

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.如果我运行此代码并多次按 F5,在某些情况下,会在旧连接断开之前创建新连接。 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?我的问题是:这是一个错误还是 socket.io 的正常行为? How can i prevent the connection flooding, simple pressing F5?如何防止连接泛滥,只需按 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.如果多次按 F5 非常快,它确实会暂时在 Chrome 中积累一些额外的 socket.io 连接,但在相对较短的时间内(可能几分钟),它会恢复并且连接的套接字总数回到 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.这是 socket.io 如何启动 socket.io 连接的问题。 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.这迫使 socket.io 仅使用 webSocket 而从不使用 HTTP 轮询,然后问题就消失了。

So, the issue is because the default behavior for socket.io is to start with an http polling version of a socket.io connection.所以,问题是因为 socket.io 的默认行为是从 socket.io 连接的 http 轮询版本开始。 After a little data is exchanged, socket.io will then attempt to switch over to a real webSocket.交换少量数据后,socket.io 将尝试切换到真正的 webSocket。 If that real webSocket works, then it will stop using the http polling connection.如果那个真正的 webSocket 工作,那么它将停止使用 http 轮询连接。

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.但是,如果你在轮询和真正的 webSocket 之间的这个转换过程中按下 F5,那么 socket.io 还没有持久连接知道它刚刚与之通信的网页现在已经消失了。 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).因此,它所能做的就是在一段时间后确定不再有来自该网页的任何传入通信,因此它应该清除它的 socket.io 连接(当您按 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).但是,如果您使用上述客户端代码关闭初始轮询模式,那么它只会使用真正的 webSocket(从不使用模拟轮询模式),并且当您按 F5 时,浏览器非常擅长清理 webSocket,因此服务器要么没有完成建立它的 socket.io 连接(在这种情况下还没有连接暂时孤立),或者它已经转换为 webSocket(浏览器将在 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.所以,这是socket.io启动的http轮询模式的设计限制。由于在该模式下没有连续连接,当该页面被F5替换时浏览器不会立即通知,因此服务器有无法知道客户刚刚消失了。 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.但是,如果您跳过 http 轮询模式并从真正的 webSocket 开始,则没有这样的时间窗口存在 socket.io 连接,但没有真正的 webSocket,因此浏览器总是会立即通知服务器关闭 webSocket页面消失时的连接。

Solution: update the versions of your socket.io packages front and back解决方案:前后更新 socket.io 包的版本

example : back : socket.io 3.0.3示例:返回:socket.io 3.0.3

example : front : socket-io-client 3.0.3示例:前面:socket-io-client 3.0.3

now is compatible and transport socket is websocket and not polling !现在是兼容的,传输套接字是 websocket 而不是轮询!

import io from ....从...导入io

const socket = io('http//localhost:3000') -> server node const socket = io('http//localhost:3000') -> 服务器节点

I had kind of the same error, I was getting multiple connections with the same user, the error was that I was using a different version on the backend and I added this piece of code on the front-end :我遇到了同样的错误,我与同一个用户建立了多个连接,错误是我在后端使用了不同的版本,我在前端添加了这段代码:

socket.on("connect_error", (err) => { console.log( connect_error due to ${err.message} ); }); socket.on("connect_error", (err) => { console.log( connect_error due to ${err.message} ); });

in that way, I could know the error, I hope this can help someone这样,我可以知道错误,我希望这可以帮助某人

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

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