Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why NodeJS KeepAlive does not seem to work as expected?

Quoted from TCP keepalive HowTo:

In order to understand what TCP keepalive (which we will just call keepalive) does, you need do nothing more than read the name: keep TCP alive. This means that you will be able to check your connected socket (also known as TCP sockets), and determine whether the connection is still up and running or if it has broken.

So why is the following code not throwing something when the internet connection is broken?

var tls = require('tls');

var socket = tls.connect(443, "google.com", function connected() {
  console.log('connected');
});

socket.setNoDelay(true);
socket.setKeepAlive(true, 0);
socket.setTimeout(0, function(){
  console.log('timeout');
});
socket.on('data', function(data) {
  console.log(data);
});
socket.on('close', function() {
  console.error("close");
});
socket.on('error', function(err) {
  console.error("error", err);
});

Tested on MacOS/Debian, with NodeJS v0.10.17

like image 582
FGRibreau Avatar asked Sep 04 '13 12:09

FGRibreau


People also ask

How does a keepalive connection work?

Keep-Alive, also known as a persistent connection, is a communication pattern between a server and a client to reduce the HTTP request amount and speed up a web page. When Keep-Alive is turned on, the client and the server agree to keep the connection for subsequent requests or responses open.

Is TCP Keepalive enabled by default?

Transmission Control Protocol (TCP) keepalives are an optional feature, and if included must default to off. The keepalive packet contains no data.

What is keepalive probe?

Answer. TCP keepalive probes provide a method to remove dead sockets and notify applications of unresponsive peers across a TCP connection. While terminating or killing a program causes a FIN packet or possibly a RST packet to be sent, a system crash, hard reboot or network outage does not generate any packets.

What is the TCP keepalive timer used for?

The TCP Keepalive Timer feature provides a mechanism to identify dead connections. When a TCP connection on a routing device is idle for too long, the device sends a TCP keepalive packet to the peer with only the Acknowledgment (ACK) flag turned on.


2 Answers

Quoting man 7 tcp:

tcp_keepalive_time (integer; default: 7200; since Linux 2.2)

The number of seconds a connection needs to be idle before TCP begins sending out keep-alive probes. Keep-alives are only sent when the SO_KEEPALIVE socket option is enabled. The default value is 7200 seconds (2 hours). An idle connection is terminated after approximately an additional 11 minutes (9 probes an interval of 75 seconds apart) when keep-alive is enabled.

So after ~10 minutes (on MacOS 10.8) node emitted an error:

error { [Error: read ETIMEDOUT] code: 'ETIMEDOUT', errno: 'ETIMEDOUT', syscall: 'read' }
like image 146
FGRibreau Avatar answered Oct 11 '22 18:10

FGRibreau


https://www.npmjs.com/package/net-keepalive

Here is a module which lets you configure TCP_KEEPINTVL and TCP_KEEPCNT per-socket basis.

Provides high-level access to socket options like TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT

var Net = require('net')
  , NetKeepAlive = require('net-keepalive')
;

// Create a TCP Server
var srv = Net.createServer(function(s){>
  console.log('Connected %j', s.address())
  // Doesn't matter what it does
  s.pipe(s)
});

// Start on some port
srv.listen(1337, function(){
  console.log('Listening on %j', srv.address())
});

// Connect to that server
var s = Net.createConnection({port:1337}, function(){
  console.log('Connected to %j', s.address())

  //IMPORTANT: KeepAlive must be enabled for this to work
  s.setKeepAlive(true, 1000)

  // Set TCP_KEEPINTVL for this specific socket
  NetKeepAlive.setKeepAliveInterval(s, 1000)

  // and TCP_KEEPCNT
  NetKeepAlive.setKeepAliveProbes(s, 1)
});
like image 33
George Avatar answered Oct 11 '22 18:10

George