node.js - 处理TCP套接字错误ECONNREFUSED

时间:2014-09-15 10:56:30

标签: node.js sockets tcp

我使用带有socket.io的node.js来让我的网页访问由TCP套接字提供的字符数据。我对node.js很新。

用户 ----> 网页< - (socket.io) - > node.js < - (TCP) - > TCP服务器

代码简洁明了:

io.on('connection', function (webSocket) {
    tcpConnection = net.connect(5558, 'localhost', function() {});

    tcpConnection.on('error', function(error) {
        webSocket.emit('error', error);
        tcpConnection.close();
    });

    tcpConnection.on('data', function(tcpData) {
        webSocket.emit('data', { data: String.fromCharCode.apply(null, new Uint8Array(tcpData))});
    });
});

在正常情况下一切正常,但我无法保证TCP服务器始终在那里。当它不是时,TCP堆栈将ECONNREFUSED返回到node.js - 这完全是预期的,我需要优雅地处理它。目前,我看到了:

events.js:72
    throw er; // Unhandled 'error' event
          ^
Error: connect ECONNREFUSED
    at errnoException (net.js:904:11)
    at Object.afterConnect [as oncomplete] (net.js:895:19)

......整个过程结束。

我已经做了很多寻找解决方案;大多数点击似乎来自程序员,他们首先询问为什么会收到ECONNREFUSED - 建议只是为了确保TCP服务器可用。没有讨论处理失败案件。

此帖子 - Node.js connectListener still called on socket error - 建议为错误添加处理程序'正如我在上面的代码中所做的那样。这正是我希望它工作的方式......除了它(对我而言),我的程序不会陷入ECONNREFUSED。

我尝试过RTFM,http://nodejs.org/api/net.html#net_event_error_1的node.js文档表明确实存在“错误”错误。事件 - 但不知道如何使用它。

其他类似SO帖子(例如Node.js Error: connect ECONNREFUSED)的答案建议全局未捕获的异常处理程序,但这对我来说似乎是一个糟糕的解决方案。这不是我的程序由于代码错误而抛出异常,它工作正常 - 它应该处理外部故障,因为它的设计目的。

所以

  • 我是以正确的方式接近这个吗? (很高兴承认这是一个新手错误)
  • 是否有可能做我想做的事情,若然,怎么做?

哦,并且:

$ node -v
v0.10.31

2 个答案:

答案 0 :(得分:18)

我运行了以下代码:

var net = require('net');

var client = net.connect(5558, 'localhost', function() {
  console.log("bla");
});
client.on('error', function(ex) {
  console.log("handled error");
  console.log(ex);
});

由于我没有打开5558,因此输出为:

$ node test.js
handled error
{ [Error: connect ECONNREFUSED]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect' }

这证明错误处理得很好......暗示错误发生在其他地方 -

正如另一个答案中所讨论的,问题实际上就是这一行:

webSocket.emit('error', error);

'错误'事件是特殊的,需要在某处处理(如果不是,则流程结束)。

只需将活动重命名为'问题'或者警告'导致整个错误对象通过socket.io socket传回到网页:

webSocket.emit('warning', error);

答案 1 :(得分:0)

我找到解决此问题的唯一方法是将网络内容包装在一个域中:

const domain = require('domain');
const net = require('net');

const d = domain.create();

d.on('error', (domainErr) => {
    console.log(domainErr.message);
});

d.run(() => {
    const client = net.createConnection(options, () => {

        client.on('error', (err) => {
            throw err;
        });
        client.write(...);
        client.on('data', (data) => {
            ...
        });
    });
});

域错误捕获在创建网络客户端之前出现的错误情况,例如无效的主机。

另请参阅:https://nodejs.org/api/domain.html