Websockets 不能发送大数据

Posted

技术标签:

【中文标题】Websockets 不能发送大数据【英文标题】:Websockets can't send large data 【发布时间】:2016-02-19 21:13:48 【问题描述】:

我有两个问题:

1. 当我在 Chrome 中发送大于 128 kb 的文本或二进制文件时,Chrome 会发送碎片化的 websocket 帧。这些帧应以最后一帧和 fin=1 结束。但 Chrome 也会发送带有未知操作码的帧。

2. 当我尝试在 Firefox 中发送大文件时,Firefox 在我的家庭网络中发送数据非常慢(~300kb/s 并且在发送 TCP 包时速度变慢)并且文件是永远不会完成。二进制文件的框架也丢失了。我用 Wireshark 跟踪了网络。 Safari 因同样的尝试而崩溃。

我在 Mac 上使用 Firefox 43.0.4,在 Mac 上使用 Chrome 48.0.2564.97 Safari 9.0.3 我在 Node.js 中使用我自己的服务器

更新 我发现了问题,但不知道解决方案。

 socket.on('data', function(data) 
    buffer = Buffer.concat([buffer, data]);
    _editBuffer();
);

Buffer.concat 会减慢传输速度。但是如何使用 + 运算符进行缓冲区连接?

【问题讨论】:

如果你不断地追加到一个每次都需要重新分配的缓冲区(可能是这里的情况,不确定),你将获得 O(N^2) 的性能。需要修改代码以避免在最终需要之前实际加入数据缓冲区集,这可能需要重新处理一些周围的逻辑。您不能使用+ 运算符来连接数组/缓冲区(如in this answer 所述,它只能添加数字和连接字符串)。 如何做到这一点?我只有 'socket on data' 事件并且必须存储传入的块,如果它只有一个 websocket 框架,就像在 Firefox 中一样。似乎在客户端分块大文件是最好的方法,所以文件可以和平写入。因为如果我在一个 websocket 帧中使用它,我必须将所有内容存储在一个缓冲区中,以取消屏蔽有效负载。是这样吗? 【参考方案1】:

我找到了解决方案。 每次二进制文件中的 websocket 帧到达服务器时,都必须使用 fs.createWriteStream 以附加模式写入该帧。之后,缓冲区必须从写入的帧中分割出来。

 var stream  = fs.createWriteStream(__dirname + '/' + fileInfo.fileName, flags:'a');
...
stream.write(payload);

【讨论】:

以上是关于Websockets 不能发送大数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 Undertow WebSockets 高效发送大型数据集

如何通过 websockets 发送结构

如何使用棘轮 websockets 将数据发送到服务器 onload?

对 Microsoft WebSockets 命名空间感到困惑

允许在 websockets 中删除消息

websocke