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

mcb*_*ood 13 javascript sockets node.js socket.io

我有这个简单的node.js Servercode使用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);
    });
});
Run Code Online (Sandbox Code Playgroud)

如果我运行此代码并按F5几次,在某些情况下会创建新连接,然后再断开旧连接.过了一段时间,我认为它的Heartbeat Timout,所有的连接将被关闭.看结果:

 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
Run Code Online (Sandbox Code Playgroud)

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

最诚挚的问候马克

jfr*_*d00 22

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

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

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

var socket = io();
Run Code Online (Sandbox Code Playgroud)

有了这个:

var socket = io({transports: ['websocket'], upgrade: false});
Run Code Online (Sandbox Code Playgroud)

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

因此,问题是因为s​​ocket.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页面消失时的连接.