javascript 分块WebSocket传输

z9smfwbn  于 2023-10-14  发布在  Java
关注(0)|答案(2)|浏览(136)

由于我经常使用WebSocket连接,所以我对底层的工作原理很感兴趣。因此,我在无尽的规范文档中挖掘了一段时间,但到目前为止,我真的找不到任何关于 * 分块传输流本身 * 的东西。
WebSocket协议称之为 * Dataframe *(描述纯数据流,因此也称为 * 非控制帧 )。就我对规范的理解而言,没有定义最大长度,也没有定义MTU(最大传输单元)值,这反过来意味着单个WebSocket Dataframe 可能包含,根据规范(!),无限数量的数据(如果我错了,请纠正我,我还是一个学生)。
阅读之后,我立即设置了我的小 Node WebSocket服务器。由于我有一个强大的 Ajax 历史(也在流和彗星),我的期望最初是这样的,“
必须有某种交互模式阅读数据,而它是传输 *"。但我错了,不是吗?
我开始的时候很小,只有 4kb 的数据。

服务器

testSocket.emit( 'data', new Array( 4096 ).join( 'X' ) );

正如预期的那样,这作为一个数据块到达客户端,

客户端

wsInstance.onmessage = function( data ) {
    console.log( data.length ); // 4095
};

所以我增加了有效负载,实际上我再次期待,在某个时候,客户端onmessage处理程序将重复触发,有效地分块传输。但令我震惊的是,它从来没有发生过(* 节点服务器 *,在 * 火狐 *,ChromeSafari 客户端测试)。我最大的负载是80 MB

testSocket.emit( 'data', new Array( 1024*1024*80 ).join( 'X' ) );

它仍然以一个大数据块的形式到达客户端。当然,这需要一段时间,即使你有一个很好的连接。这里的问题是

    • 是否有可能将这些流分块,类似于XHR readyState 3模式 *?
    • 是否有任何大小限制为一个单一的ws Dataframe *?
    • Websockets不应该传输这么大的负载吗?(这会让我再次怀疑为什么没有定义max-size)*

我可能仍然从错误的Angular 看待WebSockets,可能发送大量数据的需求并不存在,你应该在发送之前自己对任何数据进行逻辑分块/拆分?

z5btuh9x

z5btuh9x1#

首先,您需要区分 * 浏览器 * 中的WebSocket * 协议 * 和WebSocket API
WebSocket协议的帧大小限制为2^63个八位字节,但WebSocket消息可以由无限数量的帧组成。
浏览器中的WebSocket API不公开基于帧或流的API,而仅公开基于消息的API。传入消息的有效负载在提供给JavaScript之前总是完全缓冲(在浏览器的WebSocket实现中)。
其他WebSocket实现的API可以提供对经由WebSocket协议传送的有效载荷的基于帧或流的访问。例如,AutobahnPython可以。您可以在https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streaming的示例中阅读更多内容。
披露:我是原作者的高速公路和工作的塔文多。
更多注意事项:
只要浏览器JS WebSocket API中没有frame/streaming API,就只能接收/发送完整的WS消息。
单个(普通)WebSocket连接不能交错多个消息的有效负载。也就是说,如果你使用大消息,这些消息将按顺序发送,当大消息仍在运行时,你将无法在其间发送小消息。
另外请注意:您可以打开多个WS连接(通过不同的底层TCP)从单个JS / HTML页面到单个目标服务器 * 今天 *。
另外请注意:你可以在应用层中自己做“分块”:把你的东西用更小的WS消息发送,然后自己重新组装。
我同意,在一个理想的世界里,你应该在浏览器中拥有消息/帧/流API和WebSocket多路复用。这将给给予所有的权力和便利。

7vhp5slm

7vhp5slm2#

RFC 6455第1.1节:
这就是WebSocket协议所提供的:[.] HTTP轮询的替代方案,用于从网页到远程服务器的双向通信**。
如前所述,WebSockets用于网页和服务器之间的通信。请注意Web * 页面 * 和Web * 浏览器 * 之间的区别。正在使用的例子是浏览器游戏和聊天应用程序,它们交换许多小消息。
如果你想在一条消息中发送很多MB,我认为你没有按照预期的方式使用WebSockets。如果你想传输文件,那么使用一个普通的旧HTTP请求,用Content-Disposition回答,让浏览器下载一个文件。
因此,如果您解释为什么要发送如此大量的数据,也许有人可以帮助提出一个比使用WebSockets更优雅的解决方案。
此外,客户端或服务器可能会拒绝太大的消息(尽管没有明确说明 * 如何 * 拒绝):
RFC 6455第10.4节:
对于从多个帧重组后的帧大小或总消息大小,具有特定于实现和/或平台的限制的实现必须保护自己不超过这些限制。(例如,恶意端点可以尝试耗尽其对等端的内存,或通过发送单个大帧(例如,大小为2**60)或发送作为分段消息的一部分的长串小帧来发起拒绝服务攻击。)这种实现应该对帧大小和从多个帧重新组装后的总消息大小施加限制。

相关问题