如何从node.js服务器检测客户端断开连接

时间:2015-01-15 04:44:02

标签: javascript node.js disconnect

我是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);

如何了解客户端互联网断开连接。

1 个答案:

答案 0 :(得分:5)

检测"死插座的最佳方法"是定期发送应用程序级ping / keepalive消息。该消息的外观取决于您通过套接字进行通信所使用的协议。然后,只需使用计时器或其他方法检查您是否已收到" ping响应"在您将ping / keepalive消息发送给客户端后的一段时间内。

在半相关的说明中,看起来您正在使用JSON消息进行通信,但是您在每个data事件上假设一个完整的JSON字符串,这是一个不好的假设。尝试使用分隔符(对于类似的东西,换行很常见,它使得调试通信更加人性化)。

以下是如何实现此目标的简单示例:

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的作用)。

有很多方法可以解决这个问题。但是,您也可以考虑在客户端执行相同操作,以便您知道服务器也没有丢失其连接。