3

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

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

我有这段代码,但它挂在第二个 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');
        });
    }); 
});

更新代码:

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

使用更新的代码,超时似乎没有生效。当我在没有相应服务器的情况下启动此客户端时,结果显示如下,无需等待 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?
…

更新(吠叫错误的树?)

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

4

2 回答 2

7

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 while to an if, that condition won't change during a single error event. And your parens and brackets are mismatched.

于 2013-11-14T17:18:41.903 回答
5

根据我对已接受答案的评论,我发现了使用.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

所以试试下面这个版本

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')
})
于 2018-01-30T08:41:57.433 回答