Luc*_*hik 4 javascript websocket node.js
我的节点服务器应用程序正在使用 ws WebSocket 库:
socket.send(data, err => {
if (err == null) {...success...}
else {...failure...}
Run Code Online (Sandbox Code Playgroud)
客户端也使用 ws 侦听消息:
ws.on('message', message => ...handler...);
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个错误,有时,如果客户端的网络连接丢失(例如我关闭 wifi),那么看起来服务器报告消息已成功发送,但客户端的处理程序从未被调用。
问题:这可能吗?这确实是“ws”WebSocket 库的预期故障模式之一吗?成功socket.send()实际上证明了什么?
(我知道所有网络协议都在某个地方存在漏洞窗口。我试图找出 ws 库的那个窗口的确切位置,以便我可以在它之上构建正确的语义。我还没有从文档中找到该窗口正是用于 ws 的。)
可能:可能socket.send会在将消息放入其传出 TCP 缓冲区后报告成功。但是,如果网络在退出 TCP 缓冲区之前出现故障,则消息将永远丢失。
可能:socket.send一旦将消息传递到接收方的 TCP 消息队列并收到 TCP ACK 确认消息已传递,则可能报告成功,但是如果客户端的网络在调用处理程序之前出现故障,则消息将永远丢失.
根据文档,当消息发送成功时,调用回调不会出现错误。我怀疑(但我没有仔细观察)这意味着它已成功移交给操作系统(放置在发送队列中)。我很确定这并不意味着客户端已发送 TCP ACK。
TCP 连接的“问题”是,由于它们的弹性,服务器可能需要很长时间才能收到与客户端的连接已丢失的通知(因为它实际上可能并未永久丢失),并且没有某种排序连接顶部的确认层,您永远不会知道消息是否实际上已传递到客户端。
该ws文档提供了一些有关如何检测断开的连接的示例代码:https://github.com/websockets/ws#how-to-detect-and-close-broken-connections
TL;DR:定期向每个客户端发送“ping”消息,并期望客户端在一定时间范围内返回“pong”消息。
确定客户端收到 webSocket 消息的唯一方法是让客户端将您自己的自定义消息发送回服务器以表明您收到了它,并让您在服务器上等待该消息。
这是唯一有保证的端到端测试。其他任何东西都依赖于链中的其他东西,这些东西并不代表客户端实际接收并处理了消息。因为您想知道应用程序级别已经接收并处理了该消息,所以您必须在应用程序级别返回 ACK 以合法地知道应用程序级别收到了它。
仅供参考,socket.io(建立在 webSocket 之上)会为你做这件事。如果你在 socket.io 中传递一个回调socket.emit(),它会从客户端请求一个 ack,当回调被调用时,你会知道它实际上被接收了。您可以在 webSocket 中自己实现它或使用 socket.io 并且它具有内置功能。
我实际上不知道websocket.send()决定成功的级别是什么,但主要的一点是它处于低于应用程序级别的级别(正如您在问题中已经概述的那样),因此如果您想要应用程序级别的确定性,则不能仅依赖其功能 - 您必须添加额外的应用程序级别ack 或使用已经内置到 socket.io 中的那个。
| 归档时间: |
|
| 查看次数: |
3251 次 |
| 最近记录: |