简体   繁体   English

如何检测net.Socket连接是否死亡 - node.js

[英]How to detect if net.Socket connection dies - node.js

Background 背景

I am communicating with a machine using net.Socket via TCP/IP. 我正在使用net.Socket通过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! 问题是,如果我手动断开网络电缆与机器的连接,我的Node.js连接不会触发close事件,我无法知道是否有故障!

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 @robertklep提到了setKeepAlive选项,但是根据

How to test socket.setKeepAlive in NodeJS 如何在NodeJS中测试socket.setKeepAlive

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 更深入的研究表明,这高度依赖于您使用的操作系统,根据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? 如何检测连接是否已死亡?

Here's an interesting read: https://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html 这是一个有趣的读物: 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; 值得注意的是,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. 某些操作系统,特别是UNIX类型的操作系统,如果网络接口出现故障,可能会在开始使打开的连接无效之前等待很长时间。

The article also proposes a solution that may work on Node.js: enabling TCP Keepalive. 本文还提出了一个可以在Node.js上运行的解决方案:启用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. 这将在收到最后一个数据包5秒后开始检查连接。 More info here: https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay 更多信息: https//nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay

had the same issue ended up doing this to reconnect 有同样的问题最终这样做重新连接

 const _connect = () =>{ const socket = new net.Socket(); socket.connect(this.port, this.host); socket.setTimeout(10000); socket.on('timeout', () => { socket.destroy(); _connect(); }); } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM