Подтвердить что ты не робот

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
4b9b3361

Ответ 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);