节点网络套接字连接超时

4
我注意到,我的node服务器的net.createConnection()在某些情况下具有非常长的超时时间,才会发生错误(似乎是端口问题)。
我尝试连接到somedomain:9000(监听、连接并按预期工作),以及somedomain:1234(相同的域名,不同的端口,在"connect ETIMEDOUT"等待约2分钟)。
当我连接到不存在的域时,我会立即收到错误提示,但如果我连接到可达主机上的不可达端口,则不会提示错误。我需要确定一个机器是否在1秒内可达。
我该怎么办?必须有一种方法能够在不到2分钟的时间内检测到不可达端口吧?至少需要设置一种超时,使地址在一段固定的时间后被标记为不可达。
谢谢
更新:当前的连接代码如下:
this.openConnection = function() {
    try {
        console.log("[INFO] connecting to " + device.ip + ":" + device.port);
        device.clientSocket = new net.createConnection(this.port,this.ip)
            .on('connect', device.connected)
            .on('data', device.inputReceived)
            .on('error', function(err) {

                if (err.code == "ENOTFOUND") {
                    console.log("[ERROR] No device found at this address!");
                    device.clientSocket.destroy();
                    return;
                }

                if (err.code == "ECONNREFUSED") {
                    console.log("[ERROR] Connection refused! Please check the IP.");
                    device.clientSocket.destroy();
                    return;
                }


                console.log("[CONNECTION] Unexpected error! " + err.message + "     RESTARTING SERVER");


                process.exit(1);

            })
            .on('disconnect', function() {
                console.log("[CONNECTION] disconnected!");
            });
    } catch(err) {
        console.log("[CONNECTION] connection failed! " + err);
    }
};
1个回答

11

当你连接时,你可以设置自己的计时器来控制超时时间。如果在计时器触发时连接还未成功,则说明连接速度不够快。

这可以封装在一个函数中,使用单个回调或返回一个 Promise。


根据您的代码,以下是添加超时时间的尝试(未经测试的代码):

this.openConnection = function(timeout) {
    var timer;
    timeout = timeout || 2000;
    try {
        console.log("[INFO] connecting to " + device.ip + ":" + device.port);
        device.clientSocket = new net.createConnection(this.port,this.ip)
            .on('connect', function() {
                clearTimeout(timer);
                device.connected();
            })
            .on('data', function() {
                clearTimeout(timer);
                device.inputReceived();
            })
            .on('error', function(err) {
                clearTimeout(timer);
                if (err.code == "ENOTFOUND") {
                    console.log("[ERROR] No device found at this address!");
                    device.clientSocket.destroy();
                    return;
                }

                if (err.code == "ECONNREFUSED") {
                    console.log("[ERROR] Connection refused! Please check the IP.");
                    device.clientSocket.destroy();
                    return;
                }


                console.log("[CONNECTION] Unexpected error! " + err.message + "     RESTARTING SERVER");


                process.exit(1);

            })
            .on('close', function() {
                console.log("[CONNECTION] disconnected!");
            });
        timer = setTimeout(function() {
            console.log("[ERROR] Attempt at connection exceeded timeout value");
            device.clientSocket.end();
        }, timeout);
    } catch(err) {
        console.log("[CONNECTION] connection failed! " + err);
    }
};

我需要设置一个标志,向用户显示此设备是在线还是离线。你会如何做到这一点?我猜 Promise 不适用,因为我事先不知道状态会是什么,并且它不能出错。只需要一个简单的 setTimeout 吗? - Paul Schneider
@PaulSchneider - 我已经添加了一个带有超时的版本。 - jfriend00
不会在周六之前测试它...也许明天。我会告诉你的,谢谢 :) - Paul Schneider
1
@PaulSchneider - 代码中有个打字错误。每次出现 clearTimeout(timeout); 的地方,都应该改为 clearTimeout(timer);,我已经在我的回答中更正了代码。 - jfriend00
1
@redbmk - 是的,对于通用套接字对象来说似乎是这样。其他类型的套接字(如socket.io)确实有这样的事件。disconnect事件处理程序来自OP的代码,所以我只是将其保留在我的答案中。我会编辑我的答案使用close - jfriend00
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接