2015-01-04 2 views
23

Sono in difficoltà con il mio progetto hobby node.js a causa di un errore "write after end". Ho un creato un webserver node.js che tra le altre cose, invia i comandi ricevuti da una pagina HTML in poi a un altro processo utilizzando il seguente codice:Write After End error in node.js webserver

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

questo funziona fino a quando il traffico inizia ad aumentare (vale a dire la quantità di messaggi inviati e o la dimensione dei messaggi). A questo punto ricevo il seguente errore:

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) 

La mia ipotesi è che il server al 9090 è stato sopraffatto dalla quantità di traffico, dando luogo a l'errore. Come novizio completo nel mondo node.js apprezzerei davvero qualche suggerimento su come risolvere questo problema.

Si noti inoltre che il server Web sta servendo pagine su SSL (nel caso in cui ciò faccia differenza).

Grazie per aver trovato il tempo di leggere questo!

Mark

+0

Beh, ci hai mostrato il cliente presa, ma dove è il codice del server? Puoi mostrarci questo? – jakerella

risposta

30

node.js è una piattaforma async non-blocking.

Nel tuo caso,

netSocket.write(messages); 

è un metodo Async, quindi netSocket.end() viene chiamato prima di 'scrittura' è completa.

l'uso corretto sarebbe:

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

Il secondo argomento qui è una funzione di richiamata che viene chiamata una volta il metodo 'write' termina il suo lavoro.

Si consiglia di leggere/guardare più su node.js, stili asincroni e callback.

: ecco un ottimo punto di partenza: https://www.youtube.com/watch?v=GJmFG4ffJZU

E naturalmente le node.js API docs quanto riguarda prese netti.

Speranza ha aiutato :)

+0

Grazie per la rapida risposta! Ci proverò oggi dopo il lavoro e tornerò da te! – Mark

+0

Dopo aver apportato questa modifica, l'errore viene meno spesso. Pertanto segnalo questa domanda come risposta, perché la risposta mi ha aiutato ed è stata pertinente. – Mark

+0

Questo è stato davvero sorprendente, grazie Ron. Ma due domande/commenti: 1. I documenti del Node chiamano 'end' subito, non sul callback' write': https://nodejs.org/api/http.html#http_http_request_options_callback 2. Se si ' stai facendo più chiamate 'write', questo implica che dovresti gestire un intero gruppo di te stesso? –

8

In primo luogo, penso che ci sia disinformazione in un'altra risposta su socket.write() e socket.end(). E 'perfettamente normale e OK per fare loro back to back nello stesso tick:

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

Non è necessario fornire un callback per write. Il callback ti dirà quando i dati sono stati completamente svuotati dalla connessione, ma questa è una notifica opzionale di cui i programmi tipici non devono preoccuparsi.

Tuttavia, osservando la traccia dello stack, penso che il flusso di controllo della gestione degli eventi sia interrotto in questo modo. Hai un client socket.io connesso, e questo emette eventi che ascolti. Quando questi eventi si attivano, li si invia in avanti al server upstream. Quindi si termina la connessione socket upstream. A quel punto, è necessario separare (removeListener) il listener di connessione socket.io in modo che, man mano che arrivano altri eventi, non si tenti di inviarli alla connessione che hai già chiuso.

Un altro modo per dirlo è quando si chiama .end() sul socket upstream, è necessario assicurarsi che i futuri eventi in arrivo dal browser non utilizzino lo stesso socket. O devi cambiare il tuo codice per usare lo stesso socket upstream per tutti gli eventi dal corrispondente socket del browser (che è probabilmente più efficiente/corretto), MA in tal caso non chiamare .end() finché il socket del browser non si disconnette.

0

ho avuto problema simile con la compressione modulo nodo, dopo che l'aggiornamento alla più recente versione 1.6, il problema è stato risolto

npm install [email protected]