javascript Nodejs - 让客户端套接字在 5 秒超时后重试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19981040/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 17:26:53  来源:igfitidea点击:

Nodejs - getting client socket to try again after 5 sec time out

javascriptnode.jssockets

提问by extensa5620

Just starting out in node.js programming and writing a tcp socket client.

刚开始使用 node.js 编程并编写 tcp 套接字客户端。

I want the client to connect to a server. If the server is not available (i.e. server does not exist at a agreed port), i want the client to timeout and reconnect after the timeout.

我希望客户端连接到服务器。如果服务器不可用(即服务器不存在于约定的端口),我希望客户端超时并在超时后重新连接。

I have this code but it hangs at the second client.connect. What's wrong?

我有这个代码,但它挂在第二个 client.connect 上。怎么了?

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 9000;
var client = new net.Socket();

client.connect(PORT, HOST, function(){
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    client.write('I am Superman!');
});

client.on('error', function(e) {
    while (e.code == 'ECONNREFUSED') {
        console.log('Is the server running at ' + PORT + '?');`

        socket.setTimeout(1000, function() {
            console.log('Timeout for 5 seconds before trying port:' + PORT + ' again');
        }

        client.connect(PORT, HOST, function(){
            console.log('CONNECTED TO: ' + HOST + ':' + PORT);
            client.write('I am the inner superman');
        });
    }); 
});

Updated code:

更新代码:

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 9000;
var client = new net.Socket();

client.connect(PORT, HOST, function(){
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    client.write('I am Superman');
});

client.on('error', function(e) {

    while (e.code == 'ECONNREFUSED') {
        console.log('Is the server running at ' + PORT + '?');

        client.setTimeout(4000, function() {

            client.connect(PORT, HOST, function() {
                console.log('CONNECTED TO: ' + HOST + ':' + PORT);
                client.write('I am inner Superman');
            });         

            console.log('Timeout for 5 seconds before trying port:' + PORT + ' again');
        });
    }
});

client.on('data', function(data) {
    console.log('DATA: ' + data);
    client.destroy();
});

client.on('close', function() {
    console.log('Connection closed');
});

With the updated code, the timeout does not appear to take effect. When i start this client with no corresponding server, the result shows below with no 4 second wait.

使用更新后的代码,超时似乎没有生效。当我在没有相应服务器的情况下启动这个客户端时,结果显示如下,没有 4 秒的等待。

Is the server running at 9000?
Is the server running at 9000?
Is the server running at 9000?
Is the server running at 9000?
…

Update (Barking up the wrong tree?)

更新(吠错树?)

I went back to look at the socket.on('error') event and saw that the close event is called immediately after the error. So the code will close out the tcpclient without waiting for 4 seconds. Any better ideas?

我回去查看 socket.on('error') 事件,看到错误发生后立即调用了 close 事件。因此,代码将关闭 tcpclient,而无需等待 4 秒。有什么更好的想法吗?

回答by Jason Nichols

You're timeout is reversed.

你的超时被逆转了。

Should look like:

应该看起来像:

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 9000;
var client = new net.Socket();

client.connect(PORT, HOST, function(){
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    client.write('I am Superman!');
});

client.on('error', function(e) {
    if(e.code == 'ECONNREFUSED') {
        console.log('Is the server running at ' + PORT + '?');

        client.setTimeout(4000, function() {
            client.connect(PORT, HOST, function(){
                console.log('CONNECTED TO: ' + HOST + ':' + PORT);
                client.write('I am the inner superman');
            });
        });

        console.log('Timeout for 5 seconds before trying port:' + PORT + ' again');

    }   
});
client.on('data', function(data) {
    console.log('DATA: ' + data);
    client.destroy();
});
client.on('close', function() {
    console.log('Connection closed');
});

The function you want to run after the timeout is the callback. That's the one that waits for execution.

超时后要运行的函数是回调。那就是等待执行的那个。

Also, change your whileto an if, that condition won't change during a single error event. And your parens and brackets are mismatched.

此外,将您的更改whileif,该条件在单个错误事件期间不会更改。并且您的括号和括号不匹配。

回答by DKebler

per my comment on accepted answer I discovered an issue using the .connectcallback vs the 'connect'listener. Each time you call .connect it cues the callback (adds a listener) even though the connection fails. So when it finally does connect all those callbacks get called. So if you use .once('connect'..instead that won't happen. Below are logging statements from my project's client code that led me to this observation.

根据我对已接受答案的评论,我发现了使用.connect回调与'connect'侦听器的问题。每次调用 .connect 时,它都会提示回调(添加一个侦听器),即使连接失败。因此,当它最终连接时,所有这些回调都会被调用。因此,如果您.once('connect'..改为使用,则不会发生这种情况。以下是我的项目客户端代码中的日志记录语句,这些语句导致我进行了此观察。

ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
ENOENT
timeout
(node:21061) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connect listeners added. Use emitter.setMaxListeners() to increase limit  
^=== if you timeout and try .connect again eventually you hit this limit
ENOENT
timeout    <==== here is where the connection finally happens
connecting  <====  now all those listener callbacks fire.
connecting
connecting
connecting
connecting
connecting
connecting
connecting
connecting
connecting
connecting

so try this version below instead

所以试试下面的这个版本

const net = require('net')
const HOST = '127.0.0.1'
const PORT = 9000
const client = new net.Socket()

const connect = () => {client.connect(PORT, HOST)}

client.once('connect', function(){
  console.log('CONNECTED TO: ' + HOST + ':' + PORT)
  client.write('I am Superman!')
})

client.on('error', function(e) {
  if(e.code == 'ECONNREFUSED') {
    console.log('Is the server running at ' + PORT + '?')
    console.log('Waiting for 5 seconds before trying port:' + PORT + ' again')
    setTimeout(connect,5000)
  }
})

connect()

client.on('data', function(data) {
  console.log('DATA: ' + data)
  client.destroy()
})
client.on('close', function() {
  console.log('Connection closed')
})