Background
I am communicating with a machine using net.Socket
via TCP/IP.
I am able to establish the connection and to send and receive packets of Buffers, which is all fine.
Problem
The problem is that if I manually disconnect the internet cable from the machine, my Node.js connection doesn't fire the close
event and I have no means to know if something failed!
Code
let socket;
const start = async function ( config ) {
await connecToBarrier( config )
.then( () => console.log( "connected to barrrier" ) )
.catch( err => {
throw new Error( `Cannot connect to barrier: ${err}` );
} );
};
const connecToBarrier = function ( connectOpts ) {
return new Promise( ( resolve, reject ) => {
//connectOpts is an object with 'port' and 'host'
socket = net.createConnection( connectOpts, () => {
//once I receive a 'hello world' from the machine, I can continue
socket.once( "data", () => resolve() );
} );
socket.on( "connection", () => {
console.log("onConnection says we have someone!");
} );
socket.on( "error", err => {
console.log(`onError says: ${err}`);
reject(err);
} );
socket.on( "timeout", () => {
console.log("onTimeout says nothing");
reject();
} );
socket.on( "end", () => {
console.log("onEnd says nothing");
reject();
} );
socket.on( "close", err => {
console.log(`onClose says: ${err}`);
reject(err);
} );
} );
};
start();
Research
@robertklep mentioned the setKeepAlive
option, however according to
How to test socket.setKeepAlive in NodeJS
it doesn't work. A more profound research shows that this is highly dependant on the Operative System you are using, as per
So in other words, unless I am willing to wait several minutes for my heartbeats to actually do something, I don't see a way out of this.
Question
How do I detect if a connection died?
Background
I am communicating with a machine using net.Socket
via TCP/IP.
I am able to establish the connection and to send and receive packets of Buffers, which is all fine.
Problem
The problem is that if I manually disconnect the internet cable from the machine, my Node.js connection doesn't fire the close
event and I have no means to know if something failed!
Code
let socket;
const start = async function ( config ) {
await connecToBarrier( config )
.then( () => console.log( "connected to barrrier" ) )
.catch( err => {
throw new Error( `Cannot connect to barrier: ${err}` );
} );
};
const connecToBarrier = function ( connectOpts ) {
return new Promise( ( resolve, reject ) => {
//connectOpts is an object with 'port' and 'host'
socket = net.createConnection( connectOpts, () => {
//once I receive a 'hello world' from the machine, I can continue
socket.once( "data", () => resolve() );
} );
socket.on( "connection", () => {
console.log("onConnection says we have someone!");
} );
socket.on( "error", err => {
console.log(`onError says: ${err}`);
reject(err);
} );
socket.on( "timeout", () => {
console.log("onTimeout says nothing");
reject();
} );
socket.on( "end", () => {
console.log("onEnd says nothing");
reject();
} );
socket.on( "close", err => {
console.log(`onClose says: ${err}`);
reject(err);
} );
} );
};
start();
Research
@robertklep mentioned the setKeepAlive
option, however according to
How to test socket.setKeepAlive in NodeJS
it doesn't work. A more profound research shows that this is highly dependant on the Operative System you are using, as per https://stackoverflow.com/a/18678494/1337392
So in other words, unless I am willing to wait several minutes for my heartbeats to actually do something, I don't see a way out of this.
Question
How do I detect if a connection died?
Share Improve this question edited May 30, 2017 at 14:07 Flame_Phoenix asked May 30, 2017 at 11:52 Flame_PhoenixFlame_Phoenix 17.6k40 gold badges143 silver badges283 bronze badges 02 Answers
Reset to default 10Here's an interesting read: https://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html
Note in particular this remark:
It is important to note that the act of receiving data is completely passive in TCP; a socket that only reads cannot detect a dropped connection.
This is exactly what's happening in your case: your socket is waiting for new data to arrive, which never happens. Some OS'es, in particular of the UNIX type, may wait a very long time before they start invalidating open connections if a network interface went down.
The article also proposes a solution that may work on Node.js: enabling TCP Keepalive. This will periodically send packets to the peer to check if the connection is still working.
To enable this on your sockets:
socket.setKeepalive(true, 5000);
This will start checking the connection 5 seconds after it has received the last packet. More info here: https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay
I had the same issue. I ended up doing this as a fix:
const _connect = () => {
const socket = new net.Socket();
socket.connect(this.port, this.host);
socket.setTimeout(10000);
socket.on('timeout', () => {
socket.destroy();
_connect();
});
}