Ошибка записи после завершения в node.js веб-сервере
Я борюсь с моим хобби-проектом node.js из-за ошибки "write after end". У меня есть созданный веб-сервер node.js, который, среди прочего, отправляет команды, полученные с 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, я бы очень признателен за любые подсказки о том, как я могу решить эту проблему.
Обратите внимание, что веб-сервер обслуживает страницы через SSL (в случае, если это имеет значение).
Спасибо, что нашли время, чтобы прочитать это!
Марк
Ответы
Ответ 1
node.js - неблокирующая асинхронная платформа.
В вашем случае
netSocket.write(messages);
- это метод Async, поэтому netSocket.end() вызывается до завершения записи.
правильное использование:
netSocket.write(messages, function(err) { netSocket.end(); });
Второй аргумент здесь - функция обратного вызова, которая будет вызываться после того, как метод write напишет свое задание.
Я бы порекомендовал вам читать/смотреть больше о node.js, стилях асинхронизации и обратных вызовах.
вот отличное место для начала: https://www.youtube.com/watch?v=GJmFG4ffJZU
И, конечно, node.js API docs относительно сетевых сокетов.
Надеюсь, что это помогло:)
Ответ 2
Во-первых, я думаю, что в другом ответе есть сообщения об ошибках socket.write()
и socket.end()
. Совершенно нормально и нормально делать их обратно к спине в одном тике:
socket.write(everythingIPlanToSend);
socket.end();
Вам не нужно предоставлять обратный вызов write
. Обратный вызов скажет вам, когда данные были полностью выведены из соединения, но это необязательное уведомление, которое типичным программам не нужно беспокоиться.
Однако, глядя на вашу трассировку стека, я думаю, что ваш поток управления обработкой событий нарушен таким образом. У вас подключен клиент socket.io, который выдает события, которые вы слушаете. Когда эти события срабатывают, вы отправляете их на ваш восходящий сервер. Затем вы завершаете восходящее соединение сокета. В этот момент вы должны развязать (removeListener
) ваш прослушиватель сокета socket.io, чтобы при поступлении большего количества событий вы не пытались отправить им соединение, которое вы уже закрыли.
Другой способ сказать, что всякий раз, когда вы вызываете .end()
в своем восходящем сокете, вы должны убедиться, что будущие входящие события из браузера не используют тот же сокет. ИЛИ вам нужно изменить свой код, чтобы использовать один и тот же восходящий сокет для всех событий из соответствующего сокета браузера (что, вероятно, более эффективно/правильно), НО в этом случае не называть .end()
на нем, пока разводка браузера фактически не отключается.
Ответ 3
У меня была аналогичная проблема с сжатием модуля node, после того как я обновил его до последней версии 1.6, проблема была решена.
npm install [email protected]