Socket.io: Отключить событие - "закрыть транспорт", "отключить пространство имен клиентов", "транспортная ошибка" и "принудительное закрытие",

Использование socket.io v1.2.1 (только с использованием транспорта "опроса" ), иногда мои клиенты испытывают разъединения.

Около 50% времени я получаю ping timeout в моей функции обратного вызова события разъединения, что является разумным.

В других случаях я получаю transport close, client namespace disconnect, transport error и forced close. Я не нашел ссылки на те причины разъединения в документации и не смог понять их смысл из кода.

Я хочу убедиться, что я обрабатываю каждое отключение наилучшим образом (и, возможно, предотвращу их).

Возможно, кто-то может пролить немного света по этим причинам.

Ответ 1

Нет документации, это более или менее то, что я могу интерпретировать из кода:

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');
};

Одна из причин закрытия транспорта

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: есть много ошибок.

Ответ 2

К сожалению, это может случиться. Иногда, поскольку мне было несчастье иметь дело, это было из-за межсетевого экрана где-то между мной, сервером и другим клиентом.

Для тайм-аутов ping вы можете попытаться увеличить интервал ping на стороне сервера

io = require( 'socket.io' )( httpServer, { pingInterval: 60000 } );