socket.io:断开事件 – “传输closures”,“客户端命名空间断开连接”,“传输错误”和“强制closures”
使用socket.io v1.2.1(仅使用“轮询”传输),有时我的客户端会遇到断开连接。
大概有50%的时间我在我的断开事件callback函数上得到了ping timeout
,这是合理的。
其他时候,我得到transport close
, client namespace disconnect
, transport error
并forced close
。 我没有发现文档中那些断开连接的原因,也没有从代码中真正理解它们的含义。
我想确保我处理每个断开连接的最佳方式(也许阻止它们)。
也许有人可以对这些理由说一点点。
没有文档,这或多或less是我可以从代码中解释的:
Forced close
– 套接字处于closures状态
Forced close
– https://github.com/socketio/engine.io/blob/master/lib/socket.js
function onPacket(packet){ if ('ping' == packet.type && 'probe' == packet.data) { transport.send([{ type: 'pong', data: 'probe' }]); self.emit('upgrading', transport); clearInterval(self.checkIntervalTimer); self.checkIntervalTimer = setInterval(check, 100); } else if ('upgrade' == packet.type && self.readyState != 'closed') { debug('got upgrade packet - upgrading'); cleanup(); self.upgraded = true; self.clearTransport(); self.setTransport(transport); self.emit('upgrade', transport); self.setPingTimeout(); self.flush(); if (self.readyState == 'closing') { transport.close(function () { self.onClose('forced close'); }); } } else { cleanup(); transport.close(); } } Socket.prototype.close = function () { if ('open' != this.readyState) return; this.readyState = 'closing'; if (this.writeBuffer.length) { this.once('drain', this.closeTransport.bind(this)); return; } this.closeTransport(); };
closures的交通工具(这里没有理由)
Transport close
– https://github.com/socketio/engine.io/blob/master/lib/socket.js
function cleanup() { self.upgrading = false; clearInterval(self.checkIntervalTimer); self.checkIntervalTimer = null; clearTimeout(self.upgradeTimeoutTimer); self.upgradeTimeoutTimer = null; transport.removeListener('packet', onPacket); transport.removeListener('close', onTransportClose); transport.removeListener('error', onError); self.removeListener('close', onClose); } function onTransportClose(){ onError("transport closed"); }
我们得到一个客户端断开包,所以我们改变套接字状态为“closures”
Client namespace disconnect
– https://github.com/socketio/socket.io/blob/master/lib/socket.js
Socket.prototype.onpacket = function(packet){ debug('got packet %j', packet); switch (packet.type) { case parser.EVENT: this.onevent(packet); break; case parser.BINARY_EVENT: this.onevent(packet); break; case parser.ACK: this.onack(packet); break; case parser.BINARY_ACK: this.onack(packet); break; case parser.DISCONNECT: this.ondisconnect(); break; case parser.ERROR: this.emit('error', packet.data); } }; Socket.prototype.ondisconnect = function(){ debug('got disconnect packet'); this.onclose('client namespace disconnect'); };
交通接近的原因之一
Transport error
– https://github.com/socketio/engine.io/blob/master/lib/socket.js
/** * Called upon transport error. * * @param {Error} error object * @api private */ Socket.prototype.onError = function (err) { debug('transport error'); this.onClose('transport error', err); };
https://github.com/socketio/engine.io/blob/master/lib/transport.js
/** * Called with a transport error. * * @param {String} message error * @param {Object} error description * @api private */ Transport.prototype.onError = function (msg, desc) { if (this.listeners('error').length) { var err = new Error(msg); err.type = 'TransportError'; err.description = desc; this.emit('error', err); } else { debug('ignored transport error %s (%s)', msg, desc); } };
看起来他们把错误扔给了任何地方的套接字,所以find原因的唯一方法是通过阅读错误描述(不要太多的信息)或查看所有的库来找出造成错误的原因。
PD:有很多错误。
不幸的是这可能发生。 有时候,我不幸遇到这个问题,这是由于我之间,服务器和其他客户端之间的防火墙。
对于ping超时,您可以尝试在服务器端增加ping时间间隔
io = require( 'socket.io' )( httpServer, { pingInterval: 60000 } );