Как обнаружить отключение клиента от сервера node.js

Я новичок в node.js. Как определить, что клиент отключен от сервера node.js.

Вот мой код:

var net = require('net');
var http = require('http');

var host =  '192.168.1.77';
var port = 12345;//
var server = net.createServer(function (stream) {
stream.setEncoding('utf8');

stream.on('data', function (data) { 
    var comm = JSON.parse(data); 
    if (comm.action == "Join_Request"  && comm.gameId =="game1") // join request getting from client
    {
        var reply0 = new Object();
        reply0.message = "WaitRoom";
        stream.write(JSON.stringify(reply0) + "\0");   

    }
});

stream.on('disconnect', function() {
});
stream.on('close', function () {
console.log("Close");
}); 
stream.on('error', function () { 
console.log("Error");
}); 

});  

server.listen(port,host);

Как узнать об отключении интернета на стороне клиента.


person aleena mathew    schedule 15.01.2015    source источник


Ответы (1)


Лучший способ обнаружить «мертвые сокеты» — это отправлять периодические сообщения ping/keepalive на уровне приложения. То, как выглядит это сообщение, зависит от протокола, который вы используете для связи через сокет. Тогда это просто вопрос использования таймера или других средств проверки, получили ли вы «ответ ping» в течение определенного периода времени после того, как вы отправили сообщение ping/keepalive клиенту.

В полусвязанной заметке похоже, что вы используете сообщения JSON для связи, но вы предполагаете полную строку JSON для каждого события data, что является плохим предположением. Попробуйте вместо этого использовать разделитель (новая строка довольно распространена для чего-то подобного, и это делает отладку сообщения более удобочитаемой).

Вот простой пример того, как этого добиться:

var PING_TIMEOUT = 5000, // how long to wait for client to respond
    WAIT_TIMEOUT = 5000; // duration of "silence" from client until a ping is sent

var server = net.createServer(function(stream)  {
  stream.setEncoding('utf8');

  var buffer = '',
      pingTimeout,
      waitTimeout;

  function send(obj) {
    stream.write(JSON.stringify(obj) + '\n');
  }

  stream.on('data', function(data) {
    // stop our timers if we've gotten any kind of data
    // from the client, whether it's a ping response or
    // not, we know their connection is still good.
    clearTimeout(waitTimeout);
    clearTimeout(pingTimeout);

    buffer += data;
    var idx;

    // because `data` can be a chunk of any size, we could
    // have multiple messages in our buffer, so we check
    // for that here ...
    while (~(idx = buffer.indexOf('\n'))) {
      try {
        var comm = JSON.parse(buffer.substring(0, idx));

        // join request getting from client
        if (comm.action === "Join_Request"  && comm.gameId === "game1") {
          send({ message: 'WaitRoom' });
        }
      } catch (ex) {
        // some error occurred, probably from trying to parse invalid JSON
      }

      // update our buffer
      buffer = buffer.substring(idx + 1);
    }

    // we wait for more data, if we don't see anything in
    // WAIT_TIMEOUT milliseconds, we send a ping message
    waitTimeout = setTimeout(function() {
      send({ message: 'Ping' });
      // we sent a ping, now we wait for a ping response
      pingTimeout = setTimeout(function() {
        // if we've gotten here, we are assuming the
        // connection is dead because the client did not
        // at least respond to our ping message
        stream.destroy(); // or stream.end();
      }, PING_TIMEOUT);
    }, WAIT_TIMEOUT);
  });

  // other event handlers and logic ...

});

Вы также можете просто иметь один интервал вместо двух таймеров, которые проверяют отметку времени «последние полученные данные» по сравнению с текущей отметкой времени, и если она превышает некоторый промежуток времени, и мы недавно отправили сообщение ping, то вы предполагаете, что сокет/соединение мертво . Вместо этого вы также можете отправить более одного сообщения ping, и если после n сообщений ping отправлено, а ответа не получено, закрыть соединение в этот момент (это в основном то, что делает OpenSSH).

Есть много способов сделать это. Однако вы также можете подумать о том, чтобы сделать то же самое на стороне клиента, чтобы вы знали, что сервер также не потерял соединение.

person mscdex    schedule 15.01.2015