web-dev-qa-db-fra.com

Erreur d'écriture après fin dans le serveur Web node.js

Je suis aux prises avec mon projet de passe-temps node.js en raison d'une erreur "write after end". J'ai créé un serveur Web node.js qui, entre autres choses, envoie les commandes reçues d'une page HTML à un autre processus à l'aide du code suivant:

var netSocket = require('net').Socket();
netSocket.connect(9090);
netSocket.write(messages);
netSocket.end();

Cela fonctionne jusqu'à ce que le trafic commence à augmenter (c'est-à-dire le nombre de messages envoyés et/ou la taille des messages). À ce stade, j'obtiens l'erreur suivante:

Error: write after end
    at writeAfterEnd (_stream_writable.js:132:12)
    at Socket.Writable.write (_stream_writable.js:180:5)
    at Socket.write (net.js:615:40)
    at Socket.<anonymous> (/Users/mark/Documents/GitHub Repos/voice_controlled_zumo/speech_module/web_server_HTTPS.js:66:15)
    at Socket.emit (events.js:95:17)
    at Socket.onevent (/Users/mark/Documents/GitHub Repos/voice_controlled_zumo/node_modules/socket.io/lib/socket.js:327:8)
    at Socket.onpacket (/Users/mark/Documents/GitHub Repos/voice_controlled_zumo/node_modules/socket.io/lib/socket.js:287:12)
    at Client.ondecoded (/Users/mark/Documents/GitHub Repos/voice_controlled_zumo/node_modules/socket.io/lib/client.js:193:14)
    at Decoder.Emitter.emit (/Users/mark/Documents/GitHub Repos/voice_controlled_zumo/node_modules/socket.io/node_modules/socket.io-parser/node_modules/component-emitter/index.js:134:20)

Mon hypothèse est que le serveur à 9090 est surchargé par la quantité de trafic, ce qui a provoqué l'erreur. En tant que novice complet dans le monde node.js, j'apprécierais vraiment toutes les astuces permettant de résoudre ce problème.

Notez également que le serveur Web sert des pages via SSL (au cas où cela ferait une différence).

Merci d'avoir pris le temps de lire ceci!

Marque

29
Mark

node.js est une plate-forme asynchrone non bloquante.

Dans ton cas,

netSocket.write(messages);

est une méthode async, donc netSocket.end () est appelée avant que 'write' soit terminé.

l'utilisation correcte serait:

netSocket.write(messages, function(err) { netSocket.end(); });

Le deuxième argument ici est une fonction de rappel qui sera appelée une fois que la méthode 'write' aura terminé son travail.

Je vous recommande de lire/regarder davantage sur node.js, les styles async et les callbacks.

voici un excellent endroit pour commencer: https://www.youtube.com/watch?v=GJmFG4ffJZ

Et bien sûr, le noeud.js documentation de l'API concernant les sockets net.

J'espère que ça a aidé :)

35
Ron Bar

Premièrement, je pense qu’une autre réponse contient des informations erronées sur socket.write() et socket.end(). Il est parfaitement normal et OK de les faire dos à dos dans le même tick:

socket.write(everythingIPlanToSend);
socket.end();

Il n'est pas nécessaire de fournir un rappel à write. Le rappel vous indiquera quand les données auront été entièrement vidées de la connexion, mais il s'agit d'une notification facultative que les programmes types n'ont pas besoin de se préoccuper.

Cependant, en regardant votre trace de pile, je pense que votre flux de contrôle de gestion des événements est cassé de cette manière. Vous avez un client socket.io connecté qui émet des événements que vous écoutez. Lorsque ces événements se déclenchent, vous les envoyez vers votre serveur en amont. Ensuite, vous mettez fin à la connexion de prise en amont. À ce stade, vous devez dissocier (removeListener) votre écouteur de connexion socket.io, de sorte que plus vous recevez d’événements, vous ne tentez pas de leur envoyer la connexion déjà fermée.

Une autre façon de le dire est que chaque fois que vous appelez .end() sur votre socket en amont, vous devez vous assurer que les prochains événements entrants provenant du navigateur n'utilisent pas le même socket. OR vous devez changer votre code pour utiliser le même socket en amont pour tous les événements du socket du navigateur correspondant (ce qui est probablement plus efficace/correct), MAIS dans ce cas, n'appelez pas .end() dessus jusqu'à ce que le socket du navigateur se déconnecte.

15
Peter Lyons

J'avais un problème similaire avec la compression du module de noeud. Après l'avoir mise à jour vers la dernière version 1.6, le problème était résolu.

npm install [email protected]
1
shacharsol