web-dev-qa-db-ja.com

node.js Webサーバーでの書き込み後終了エラー

「write after end」エラーが原因で、node.js趣味プロジェクトに苦労しています。 node.js Webサーバーを作成しました。これは、とりわけ、次のコードを使用してHTMLページから受信したコマンドを別のプロセスに送信します。

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

これは、トラフィックが増加し始めるまで機能します(つまり、送信されるメッセージの量またはメッセージのサイズ)。この時点で、次のエラーが表示されます。

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)

私の推測では、9090のサーバーはトラフィック量に圧倒されており、エラーが発生していると考えられます。 node.jsの世界の初心者として、この問題を解決するためのヒントをいただければ幸いです。

また、WebサーバーがSSLを介してページを提供していることにも注意してください(違いがある場合)。

これを読んでくれてありがとう!

マーク

29
Mark

node.jsは、非ブロッキング非同期プラットフォームです。

あなたの場合、

netSocket.write(messages);

は非同期メソッドであるため、「書き込み」が完了する前にnetSocket.end()が呼び出されます。

正しい使用法は次のとおりです。

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

ここの2番目の引数は、「write」メソッドがジョブを完了すると呼び出されるコールバック関数です。

Node.js、非同期スタイル、コールバックについて詳しく読むことをお勧めします。

ここから始めるのに最適な場所です。 https://www.youtube.com/watch?v=GJmFG4ffJZ

そしてもちろん、node.js API docs ネットソケットに関して。

それが助けたことを願っています:)

35
Ron Bar

最初に、socket.write()socket.end()についての別の回答に誤った情報があると思います。同じティックで連続して実行することは完全に正常であり、問​​題ありません。

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

writeにコールバックを提供する必要はありません。コールバックは、データが接続から完全にフラッシュされると通知しますが、これは、典型的なプログラムが自分自身に関係する必要のないオプションの通知です。

ただし、スタックトレースを見ると、イベント処理制御フローがこのように壊れていると思います。接続されたsocket.ioクライアントがあり、それがリッスンするイベントを発行します。これらのイベントが発生すると、それらを上位サーバーに送信します。次に、アップストリームソケット接続を終了します。その時点で、socket.io接続リスナーのバインドを解除(removeListener)する必要があります。これにより、より多くのイベントが到着しても、既に閉じている接続にそれらを送信しようとはしません。

別の言い方をすれば、アップストリームソケットで.end()を呼び出すときはいつでも、ブラウザからの今後の着信イベントが同じソケットを使用しないようにする必要があります。 OR対応するブラウザソケットからのすべてのイベントに同じアップストリームソケットを使用するようにコードを変更する必要があります(これはおそらくより効率的/正確です)、しかしその場合は.end().

15
Peter Lyons

ノードモジュールの圧縮で同様の問題が発生しました。最新バージョン1.6に更新した後、問題は解決しました

npm install [email protected]
1
shacharsol