最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to detect if net.Socket connection dies - node.js - Stack Overflow

programmeradmin1浏览0评论

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 0
Add a comment  | 

2 Answers 2

Reset to default 10

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

发布评论

评论列表(0)

  1. 暂无评论