Node.js - обработка ошибки сокета TCP ECONNREFUSED
Я использую node.js с socket.io, чтобы предоставить моей веб-странице доступ к символьным данным, обслуживаемым сокетом 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 все еще вызывает ошибку сокета - предлагает добавить обработчик для события "error", как я это делал в коде выше. Это именно то, как я хотел бы, чтобы он работал... кроме этого нет (для меня), моя программа не захватывает ECONNREFUSED.
Я попытался использовать RTFM, а node.js docs на http://nodejs.org/api/net.html#net_event_error_1 предположить, что действительно есть ошибка '- но не подсказывайте, как его использовать.
Ответы на другие похожие сообщения SO (такие как node.js Ошибка: подключение ECONNREFUSED) советуют глобальный обработчик неперехваченных исключений, но это похоже на плохое решение мне. Это не моя программа, которая бросает исключение из-за плохого кода, он отлично работает - предполагается, что он обрабатывает внешние сбои, как это было предусмотрено.
Итак,
- Я подхожу к этому правильно? (с удовольствием признаю, что это ошибка новичка).
- Можно ли делать то, что я хочу делать, и если да, то как?
Oh и:
$ node -v
v0.10.31
Ответы
Ответ 1
Я запустил следующий код:
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);
Событие "error" является особенным и должно быть обработано где-то (если это не так, процесс завершается).
Простое переименование события в "проблема" или "предупреждение" приводит к тому, что весь объект ошибки передается обратно через сокет socket.io до веб-страницы:
webSocket.emit('warning', error);
Ответ 2
ОК, немного неловко, оказывается, что проблема на самом деле такова:
webSocket.emit('error', error);
Мое намерение заключалось в следующем:
- ловушки TCP-ошибок (например, ECONNREFUSED)
- "перебросить" их через сокет socket.io на веб-страницу клиента.
- обрабатывать их каким-то образом на веб-странице (хотя, конечно, с некоторой переработкой/санитацией каким-то образом для отображения пользователю)
Однако событие "error" является особенным и должно быть обработано где-то (чего я не делал - отсюда завершение процесса).
Простое переименование события в "проблема" приводит к тому, что весь объект ошибки передается обратно через сокет socket.io до веб-страницы:
webSocket.emit('problem', error);