【问题标题】:How to detect if net.Socket connection dies - node.js如何检测 net.Socket 连接是否断开 - node.js
【发布时间】:2017-10-30 21:15:19
【问题描述】:

背景

我正在通过 TCP/IP 与使用 net.Socket 的机器进行通信。

我能够建立连接并发送和接收缓冲区数据包,这一切都很好。

问题

问题是,如果我手动断开网络电缆与机器的连接,我的 Node.js 连接不会触发 close 事件,我无法知道是否出现故障!

代码

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();

研究

@robertklep 提到了setKeepAlive 选项,但是根据

How to test socket.setKeepAlive in NodeJS

它不起作用。更深入的研究表明,这高度依赖于您使用的操作系统,如https://stackoverflow.com/a/18678494/1337392

所以换句话说,除非我愿意等待几分钟让我的心跳真正做某事,否则我看不到出路。

问题

如何检测连接是否断开?

【问题讨论】:

    标签: javascript node.js sockets tcp-ip


    【解决方案1】:

    这是一个有趣的阅读:https://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html

    特别注意这句话:

    需要注意的是,接收数据的行为在 TCP 中是完全被动的;仅读取的套接字无法检测到断开的连接。

    这正是您的情况:您的套接字正在等待新数据到达,而这永远不会发生。如果网络接口出现故障,某些操作系统,尤其是 UNIX 类型的操作系统,可能会等待很长时间才能开始使打开的连接无效。

    文章还提出了一个可能适用于 Node.js 的解决方案:启用 TCP Keepalive。这将定期向对等方发送数据包以检查连接是否仍在工作。

    要在您的套接字上启用此功能:

    socket.setKeepalive(true, 5000);
    

    这将在收到最后一个数据包 5 秒后开始检查连接。更多信息在这里:https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay

    【讨论】:

    • 如果连接同时中断会发生什么?哪个 net.Socket 甚至会被触发?
    • 根据上面的代码,没有任何事件被触发!
    • 看来 setKeepAlive 在 Node.js 中不可靠 stackoverflow.com/questions/20561596/… ...太好了,正是我需要的。不错的尝试,感谢 ++ 的帮助!另外,很高兴再次见到你:D
    • 嗯,这取决于您的操作系统设置,此时它将认为连接已失效。对于 Linux,它可能仍然需要 11 分钟才能停止发送 keep-alives 并声明连接已终止。不过,您可以减少该时间:tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html setKeepAlive 所做的是减少内核开始发送保持活动数据包的默认“等待时间”(在 Linux 上为 2 小时......)
    【解决方案2】:

    我有同样的问题。我最终这样做是为了解决这个问题:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多