node.js - 处理 TCP 套接字错误 ECONNREFUSED
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25846475/
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
node.js - handling TCP socket error ECONNREFUSED
提问by Chris Mead
I'm using node.js with socket.io to give my web page access to character data served by a TCP socket. I'm quite new to node.js.
我正在使用 node.js 和 socket.io 来让我的网页访问 TCP 套接字提供的字符数据。我对 node.js 很陌生。
User----> Web Page<--(socket.io)--> node.js<--(TCP)--> TCP Server
用户----> 网页<--(socket.io)--> node.js<--(TCP)--> TCP服务器
The code is mercifully brief:
代码非常简短:
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))});
});
});
It all works just fine in the normal case, but I can't guarantee that the TCP server will be there all the time. When it isn't, the TCP stack returns ECONNREFUSED to node.js - this is entirely expected and I need to handle it gracefully. Currently, I see:
在正常情况下一切正常,但我不能保证 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)
... and the whole process ends.
……整个过程就结束了。
I've done a lot of searching for solutions to this; most hits seem to be from programmers asking why ECONNREFUSED is received in the first place - and the advice is simply to make sure that the TCP server is available. No discussing of handling failure cases.
我已经做了很多寻找解决方案的工作;大多数点击似乎来自程序员询问为什么首先收到 ECONNREFUSED - 建议只是确保 TCP 服务器可用。不讨论处理失败案例。
This post - Node.js connectListener still called on socket error- suggests adding a handler for the 'error' event as I've done in the code above. This is exactly how I would like it to work ... except it doesn't (for me), my program does not trap ECONNREFUSED.
这篇文章 - Node.js connectListener 仍然调用套接字错误- 建议为 'error' 事件添加一个处理程序,就像我在上面的代码中所做的那样。这正是我希望它工作的方式......除了它没有(对我而言),我的程序不会捕获 ECONNREFUSED。
I've tried to RTFM, and the node.js docs at http://nodejs.org/api/net.html#net_event_error_1suggest that there is indeed an 'error' event - but give little clue how to use it.
我尝试过 RTFM,http://nodejs.org/api/net.html#net_event_error_1 上的 node.js 文档表明确实存在“错误”事件 - 但几乎没有提供如何使用它的线索。
Answers to other similar SO posts (such as Node.js Error: connect ECONNREFUSED) advise a global uncaught exception handler, but this seems like a poor solution to me. This is not my program throwing an exception due to bad code, it's working fine - it's supposed to be handling external failures as it's designed to.
对其他类似 SO 帖子(例如Node.js Error: connect ECONNREFUSED)的回答建议全局未捕获异常处理程序,但这对我来说似乎是一个糟糕的解决方案。这不是我的程序由于错误代码而抛出异常,它运行良好 - 它应该按照设计处理外部故障。
So
所以
- Am I approaching this in the right way? (happy to admit this is a newbie error)
- Is it possible to do what I want to do, and if so, how?
- 我是否以正确的方式解决这个问题?(很高兴承认这是一个新手错误)
- 是否可以做我想做的事情,如果可以,如何做?
Oh, and:
哦,还有:
$ node -v
v0.10.31
采纳答案by alandarev
I ran the following code:
我运行了以下代码:
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);
});
As I do not have 5558 open, the output was:
由于我没有打开 5558,输出是:
$ node test.js
handled error
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' }
This proves that the error gets handled just fine... suggesting that the error is happening else-where.
这证明错误得到了很好的处理......表明错误发生在其他地方。
As discussed in another answer, the problem is actually this line:
正如在另一个答案中所讨论的,问题实际上是这一行:
webSocket.emit('error', error);
The 'error' event is special and needs to be handled somewhere (if it isn't, the process ends).
'error' 事件是特殊的,需要在某处处理(如果不是,则过程结束)。
Simply renaming the event to 'problem' or 'warning' results in the whole error object being transmitted back through the socket.io socket up to the web page:
简单地将事件重命名为“问题”或“警告”会导致整个错误对象通过 socket.io 套接字传输回网页:
webSocket.emit('warning', error);
回答by Jan Bauer
The only way I found to fix this is wrapping the net stuff in a domain:
我发现解决此问题的唯一方法是将网络内容包装在域中:
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) => {
...
});
});
});
The domain error captures error conditions which arise before the net client has been created, such as an invalid host.
域错误捕获在创建网络客户端之前出现的错误条件,例如无效的主机。
See also: https://nodejs.org/api/domain.html

