【问题标题】:Write After End error in node.js webserver在 node.js 网络服务器中写入结束后错误
【发布时间】:2015-01-04 20:10:59
【问题描述】:

由于“结束后写入”错误,我正在为我的 node.js 爱好项目而苦苦挣扎。我创建了一个 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 提供页面(以防万一)。

感谢您抽出宝贵时间阅读本文!

标记

【问题讨论】:

  • 好吧,您已经向我们展示了套接字客户端,但是服务器代码在哪里?你能告诉我们吗?

标签: javascript node.js sockets


【解决方案1】:

NodeJS 是一个非阻塞异步平台。

在你的情况下,

netSocket.write(messages);

是一个异步方法;因此,netSocket.end()write 完成之前被调用。

正确的用法是:

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

这里的第二个参数是一个回调函数,一旦'write'方法完成它的工作就会被调用。

我建议您阅读/观看有关 NodeJS、异步样式和回调的更多信息。

这是一个很好的起点:https://www.youtube.com/watch?v=GJmFG4ffJZU

当然还有关于网络套接字的 NodeJS API docs

【讨论】:

  • 感谢您的快速回复!今天下班后我会试试这个,然后回复你!
  • 进行此更改后,错误出现的频率降低了。因此,我将此问题标记为已回答,因为该答案对我有所帮助并且具有相关性。
  • 这真是令人大开眼界,谢谢罗恩。但是有两个问题/cmets:1. Node 自己的文档立即调用 end,而不是在 write 回调:nodejs.org/api/http.html#http_http_request_options_callback 2. 如果您正在执行多个 write 调用,这意味着您必须管理一大堆自己的状态?
  • 顺便说一句,目前 API 文档本身会在代码示例中至少两次使用 req.write(...); req.end(); 引发不良做法。
  • 我对此非常重视,但我只想说,如果您像这样使用 async/await,这可以变得更简单:await netSocket.write(messages); netSocket.end() :)
【解决方案2】:

首先,我认为关于socket.write()socket.end() 的另一个答案存在错误信息。在同一滴答声中背靠背进行是完全正常的:

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

您无需向write 提供回调。回调将告诉您数据何时完全从连接中清除,但这是典型程序不需要关心的可选通知。

但是,查看您的堆栈跟踪,我认为您的事件处理控制流以这种方式被破坏了。你连接了一个 socket.io 客户端,它会发出你监听的事件。当这些事件触发时,您将它们发送到您的上游服务器。然后结束上游套接字连接。此时,您必须取消绑定 (removeListener) 您的 socket.io 连接侦听器,这样当更多事件到达时,您就不会尝试将它们发送到您已经关闭的连接上。

另一种说法是,每当您在上游套接字上调用.end() 时,您必须确保将来来自浏览器的传入事件不会使用同一个套接字。或者您必须更改代码以对来自相应浏览器套接字的所有事件使用相同的上游套接字(这可能更有效/更正确),但在这种情况下,在浏览器套接字实际断开之前不要调用.end() .

【讨论】:

  • 赞成在堆栈跟踪中发现 socket.io。很好的侦探工作。这应该是公认的答案。
【解决方案3】:

node模块压缩也有类似的问题,更新到最新版本1.6后,问题解决了

npm install compression@1.6.0

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 2018-09-23
    相关资源
    最近更新 更多