Socket.io v1.2.1を使用すると(「ポーリング」トランスポートのみを使用)、クライアントで切断が発生することがあります。
約50%の確率でping timeout
切断イベントのコールバック関数で。これは合理的です。
また、transport close
、client namespace disconnect
、transport error
およびforced close
。ドキュメントでこれらの切断理由への参照を見つけることができず、コードからそれらの意味を実際に理解することができませんでした。
それぞれの切断を最善の方法で処理するようにしたい(そしておそらくそれらを防ぐ)。
たぶん誰かがこれらの理由について少し光を当てることができます。
ドキュメントはありません、これは多かれ少なかれ私がコードから解釈できるものです:
Forced close
-ソケットは閉じた状態です
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();
};
閉鎖された交通機関(ここでは理由はありません)
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");
}
クライアント切断パケットを受け取ったので、ソケットの状態を「閉じる」に変更します
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');
};
輸送が終了する理由の1つ
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);
}
};
どこからでもソケットにエラーをスローしているように見えるので、原因を見つける唯一の方法は、エラーの説明(情報が多すぎない)を読むか、すべてのライブラリを調べてエラーの原因を見つけることです。
PD:エラーがたくさんあります。
残念ながら、これが発生する可能性があります。時々、私が対処するのに不幸があったので、それは私、サーバーと他のクライアントの間のどこかにファイアウォールが原因でした。
Pingタイムアウトの場合、サーバー側でping間隔を増やしてみてください。
io = require( 'socket.io' )( httpServer, { pingInterval: 60000 } );