socket.io:断开连接事件 - 'transport close','client namespace disconnect','transport error'和'forced close'

Gil*_*tzi 11 javascript html5 node.js socket.io

使用socket.io v1.2.1(仅使用"轮询"传输),有时我的客户端会断开连接.

我有大约50%的时间使用ping timeout断开连接事件回调函数,这是合理的.

其他时候,我得到transport close,client namespace disconnect,transport errorforced close.我在文档中没有找到任何关于断开原因的参考,并且无法从代码中真正理解它们的含义.

我想确保我以最好的方式处理每个断开连接(并且可能阻止它们).

也许有人可以对这些原因有所了解.

Jai*_*iro 6

没有文档,这或多或少是我可以从代码中解释的:

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

关闭的交通工具(这里没有理由)

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

我们得到了一个客户端断开数据包,所以我们将套接字状态更改为“关闭”

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

交通关闭的原因之一

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

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

似乎他们从任何地方向套接字抛出错误,所以找到原因的唯一方法是阅读错误描述(不要太多信息)或查看他们所有的库以找出导致错误的原因。

PD:有很多错误。


kay*_*nce -2

不幸的是,这可能会发生。有时,正如我不幸遇到的那样,这是由于我、服务器和其他客户端之间的防火墙造成的。

对于 ping 超时,您可以尝试增加服务器端的 ping 间隔

io = require( 'socket.io' )( httpServer, { pingInterval: 60000 } );
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,增加“pingInterval”值只是一种解决方法,而不是实际的解决方案。这将使真正失去连接的客户端看起来仍然处于连接状态。 (3认同)