因为我在更常规的基础上使用WebSocket连接,所以我对如何在幕后工作感兴趣。所以我在一段时间内深入研究了无休止的规范文档,但到目前为止,我无法真正找到关于分块传输流本身的任何内容。
WebSocket协议将其称为数据帧(描述纯数据流,因此它也称为非控制帧)。据我了解规范,没有定义的最大长度和没有定义的MTU(最大传输单位)值,这反过来意味着单个WebSocket数据框可能包含spec(!),无限量的数据(如果我在这里错了,请纠正我,我还是学生。)
阅读完之后,我立即设置了我的小 Node WebSocket服务器。由于我有一个强大的 Ajax 历史(也在流媒体和Comet上),我的期望原来就像是,“在传输数据时必须有某种交互模式来读取数据”。但那里我错了,不是吗?
我从 4kb 的数据开始很小。
服务器
testSocket.emit( 'data', new Array( 4096 ).join( 'X' ) );
和预期的一样,它作为一个数据块到达客户端
客户端
wsInstance.onmessage = function( data ) {
console.log( data.length ); // 4095
};
所以我增加了有效负载,实际上我再次期待,在某些时候,客户端onmessage
处理程序将重复触发,effectivley对传输进行分块。但令我震惊的是,它从未发生过( node-server ,在 firefox , chrome 和 safari 客户端上测试过 - 侧)。我最大的有效载荷是 80 MB
testSocket.emit( 'data', new Array( 1024*1024*80 ).join( 'X' ) );
它仍然存在于客户端上的一个大数据块中。当然,即使你有一个非常好的连接,这需要一段时间。这里的问题是
我可能仍然从WebSockets的错误角度看,可能是发送大量数据的需要不存在,你应该在发送之前自己逻辑地分块/拆分任何数据?
答案 0 :(得分:80)
首先,您需要在 browsers 中区分WebSocket 协议和WebSocket API 。
WebSocket协议的帧大小限制为2 ^ 63个八位字节,但WebSocket消息可以由无限数量的帧组成。
浏览器中的WebSocket API不会公开基于帧的API或流API,而只会公开基于消息的API。在将消息提供给JavaScript之前,传入消息的有效负载总是被完全缓冲(在浏览器的WebSocket实现中)。
其他WebSocket实现的API可以提供对通过WebSocket协议传输的有效负载的基于帧或流的访问。例如,AutobahnPython可以。您可以在此处的示例https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streaming中阅读更多内容。
披露:我是Autobahn的原作者,并为Tavendo工作。
更多注意事项:
只要浏览器JS WebSocket API中没有框架/流API,您就只能接收/发送完整的WS消息。
单个(普通)WebSocket连接无法交错多条消息的有效负载。因此,如果您使用大型邮件,那些邮件将按顺序发送,并且您仍然无法在大型邮件仍处于运行状态时在其间发送小邮件。
即将推出的WebSocket扩展(扩展是扩展协议的内置机制):WebSocket多路复用。这允许在单个底层TCP连接上具有多个(逻辑)WebSocket连接,这具有多个优点。
另请注意:您可以从单个JS / HTML页面今天打开多个WS连接(通过不同的底层TCP)到单个目标服务器。
另请注意:您可以在应用程序层中自行“分块”:将您的内容发送到较小的WS消息中,然后重新自行组装。
我同意,在一个理想的世界中,你在浏览器和WebSocket多路复用中都有消息/帧/流API。这将提供所有的力量和便利。
答案 1 :(得分:10)
这就是WebSocket协议提供的内容:[...] HTTP轮询的替代方法,用于从网页到远程服务器的双向通信。
如上所述,WebSockets用于网页和服务器之间的通信。请注意网站页面与网络浏览器之间的区别。正在使用的示例是浏览器游戏和聊天应用程序,他们挑选了许多小消息。
如果你想在一条消息中发送许多MB,我认为你没有按照预期的方式使用WebSockets。如果要传输文件,请使用Plain Old Http Request执行此操作,并使用Content-Disposition
进行回答,让浏览器下载文件。
因此,如果您解释为什么要发送如此大量的数据,也许有人可以帮助提出比使用WebSockets更优雅的解决方案。
此外,客户端或服务器可能会拒绝过大的消息(虽然没有明确声明 它会拒绝):
具有特定于实现和/或平台的实现 关于帧大小或总消息大小的限制 从多个框架重新组装必须保护自己免受攻击 超过这些限制。 (例如,恶意端点可以尝试 耗尽其同伴的记忆或发起拒绝服务攻击 发送单个大帧(例如,大小为2 ** 60)或通过发送 长片段的小帧,是碎片的一部分 消息。)这样的实现应该对框架施加限制 从多个重组后的大小和总消息大小 帧。