web-dev-qa-db-fra.com

node.js - traitement TCP erreur de socket ECONNREFUSED

J'utilise node.js avec socket.io pour donner à ma page Web un accès aux données de caractères servies par un socket TCP. Je suis assez nouveau pour node.js.

Utilisateur ----> Page Web <- (socket.io) -> node.js <- (TCP) -> TCP Serveur

Le code est heureusement bref:

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

Tout fonctionne parfaitement dans le cas normal, mais je ne peux pas garantir que le serveur TCP sera présent tout le temps. Si ce n'est pas le cas, la pile TCP renvoie ECONNREFUSED à node.js - c'est tout à fait prévu et je dois le gérer avec élégance. Actuellement, je vois:

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)

... et tout le processus se termine.

J'ai beaucoup cherché des solutions à cela; la plupart des hits semblent provenir de programmeurs qui demandent pourquoi ECONNREFUSED est reçu - et le conseil est simplement de s'assurer que le serveur TCP est disponible. Pas de discussion sur le traitement des cas d'échec.

Cet article - Node.js connectListener continue d'appeler l'erreur de socket - suggère d'ajouter un gestionnaire pour l'événement 'error' comme je l'ai fait dans le code ci-dessus. C’est exactement ce que je voudrais que cela fonctionne ... sauf que ce n’est pas (pour moi), mon programme ne piège pas ECONNREFUSED.

J'ai essayé de RTFM, et les documents node.js à http://nodejs.org/api/net.html#net_event_error_1 suggèrent qu'il y a bien un événement 'error' - mais donne peu d'indices pour savoir comment utilise le.

Les réponses à d'autres SO publications similaires (telles que Erreur Node.js: connect ECONNREFUSED ) conseillent un gestionnaire d'exception non capturé global, mais cela me semble une mauvaise solution. Ce n'est pas mon programme qui jette une exception à cause d'un code incorrect, il fonctionne bien - il est supposé gérer les défaillances externes comme prévu.

Alors

  • Est-ce que je l'aborde de la bonne façon? (heureux d'admettre qu'il s'agit d'une erreur de débutant)
  • Est-il possible de faire ce que je veux faire, et si oui, comment?

Oh et:

$ node -v
v0.10.31
15
Chris Mead

J'ai couru le code suivant:

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

Comme je n'ai pas ouvert 5558, le résultat était:

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

Cela prouve que l'erreur est traitée correctement… ce qui suggère que l'erreur se produit ailleurs.

Comme discuté dans une autre réponse, le problème est en réalité cette ligne:

webSocket.emit('error', error);

L'événement 'erreur' est spécial et doit être géré quelque part (si ce n'est pas le cas, le processus se termine).

Si vous renommez simplement l'événement en 'problème' ou 'avertissement', l'intégralité de l'objet d'erreur sera retransmise via la socket socket.io jusqu'à la page Web:

webSocket.emit('warning', error);
16
alandarev

La seule façon pour moi de résoudre ce problème consiste à envelopper le contenu net dans un domaine:

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) => {
            ...
        });
    });
});

L'erreur de domaine capture les conditions d'erreur qui se sont produites avant la création du client Web, telles qu'un hôte non valide.

Voir aussi: https://nodejs.org/api/domain.html

0
Jan Bauer