WebSocket 如何压缩消息?

IT技术 javascript json websocket socket.io
2021-03-09 05:30:08

JSON.stringify 显然不是很节省空间。例如,[123456789,123456789] 占用 20 多个字节,而它可能只需要大约 5 个字节。 websocket 在发送到流之前是否压缩其 JSON?

4个回答

从本质上讲,WebSocket 只是一组文本或二进制数据的框架。

它本身不执行压缩。

然而,WebSocket 规范允许扩展,并且已经有多种压缩扩展(其中之一的正式规范已经完成)。

截至今天(2018 年 8 月),公认的压缩规范是permessage-deflate.

在野外看到的一些扩展:

  • permessage-deflate - 使用 deflate 压缩整个消息的正式规范的名称,而不管 websocket 帧的数量。
  • x-webkit-deflate-frame- 一种早期提议的压缩,用于压缩每个原始 websocket 数据帧。在 Chrome 和 Safari 中使用。(现在已在 Chrome 和 Safari 中弃用)
  • perframe-deflate- 上述压缩的重命名版本。被各种 websocket 服务器实现所使用,也曾短暂地出现在各种基于 WebKit 的客户端中(在现代浏览器中完全弃用,但仍然出现在各种 WebSocket 客户端库中)

值得注意的是,该permessage-deflate扩展是 PMCE(每消息压缩扩展)系列中的第一个,最终将包括其他压缩方案(正在讨论的permessage-bzip2permessage-lz4、 和permessage-snappy

你能按照今天的更新更新你的答案吗(我的意思是 2016 年底)
2021-04-27 05:30:08
正如 Joakim 所提到的,permessage-deflate尚未正式发行。FWIW,Chromium 拥有它(但您需要手动启用)并且他们“打算很快发货”:groups.google.com/a/chromium.org/forum/#!topic/blink-dev/...
2021-05-01 05:30:08
谢谢@Joakim Erdfelt,但是 permessage-deflate 使用 gzip 吗?我正在尝试通过 websocket 管道压缩 gzip 数据。
2021-05-10 05:30:08
@NiCkNewman 扩展permessage-deflatedeflate算法,gzip 是不同的。如果您自己在扩展之外执行此操作,请注意您只能使用 BINARY 消息(对于 websocket 协议),因为压缩的 TEXT 消息将违反 rfc-6455 规范(要求 TEXT 消息为 UTF-8)
2021-05-17 05:30:08

websocket 是否在发送到流之前压缩其 JSON?

简短的回答是:有时,但你不能依赖它

正如 Joakim Erdfelt 恰当地指出的那样,Websocket 连接支持文本和二进制消息。

JSON 只是传输数据的一种方式,具有通用性和易用性的优点(但就空间而言是浪费的)。

您可以使用 Websocket API 轻松传输二进制数据,以牺牲其他问题(例如endieness、字长、解析等)为代价来消除带宽开销。

许多浏览器还支持 Websocket 消息压缩作为 Websocket 协议的扩展(尽管服务器可能不支持该扩展)。

使用Sec-WebSocket-ExtensionsHTTP 标头协商扩展协商通常由客户端/服务器实现,而不提供公共 API 来控制它们。

直到 2015 年,还有许多方法和实现,但自 2015 年 12 月以来, RFC 7692 是消息压缩的唯一真正竞争者,事情变得更加清晰。

RFC 7692 在将整个消息包装(可能是分段)到 Websocket“数据包”之前压缩整个消息,使其比以前的一些压缩方案更容易实现。

当前草案提供了permessage-foo压缩协商方案(foo请求/支持的压缩在哪里)。

我只是permessage-deflate自己体验了扩展。

请注意扩展协商是可选的,这意味着即使您的服务器支持扩展,潜在的网络客户端通常也可以在不压缩的情况下协商连接。

此外,RFC 7692 支持选择性压缩,这意味着某些消息可能会被压缩,而另一些则不会被压缩......

...例如,[123456789,123456789]可能会按原样发送,因为它的长度表明它不太可能值得进行压缩。

支持permessage-deflate(RFC 7692),2017 年 8 月 8 日:

这是评论中信息的组合,最后更新于 2017 年 8 月 8 日。

如果我错过了什么,请在此处添加它们并更新日期。

已知浏览器支持

  • 自 32 年以来的铬
  • 自 37 年以来的 Mozilla Firefox
  • Safari - 不受支持(10.1.2 似乎使用x-webkit-deflate-frame
  • Microsoft Edge - 从版本 40 起不受支持

已知服务器支持

评论者:不要担心更新原始帖子中的信息。这是 StackOverflow 的一部分:)
2021-04-21 05:30:08
自 Google Chrome 32 和 Mozilla Firefox 37 以来,似乎都支持 permessage-deflate。截至 2017 年 8 月(Edge 40),我没有看到 Microsoft Edge 支持它的证据。在 Python 服务器端,截至 2017 年 8 月,似乎只有 Crossbar.io (Autobahn)、wspy 和 Tornado 支持它。
2021-05-02 05:30:08
@JohnZwinck 我将信息添加到答案中,以便将来的编辑更容易更新。
2021-05-03 05:30:08
自 2020 年 1 月起,Safari 似乎无法正常工作(Firefox 在此情况下)。Safari:“WebSocket 连接到‘ws://192.1.1.100:8080/ws’失败:无法压缩帧”
2021-05-06 05:30:08
@JohnZwinck - 添加到当前状态,Safari 使用x-webkit-deflate-frame并且在服务器端,Faye 支持permessage-defaltenode.js。
2021-05-13 05:30:08

您可以使用Unisox压缩技术来压缩通过 Websocket 发送的文本。然而,这并未与规范集成,实现者负责压缩一侧并在另一侧解压缩。

Unisox 通过基于流行符号的已知频率(熵编码)为给定字符集中的每个字母分配固定的无前缀代码来实现压缩。它还单独编码重复字母集(字典编码)。对于 Unicode 字符,使用增量编码。本文提供更多信息

到目前为止,它已在CJavascript 中实现

免责声明:我是 Unisox 的开发者。

Websockets 发送原始字节。
他们不知道也不关心这些字节代表什么。

如果你想压缩数据,你需要在发送之前自己压缩它。

请注意,Chrome 支持 gzip 用于 websocket 连接。(假设您的服务器也这样做)

gzip 是否会像这样压缩数字字符串(我猜不是)?
2021-04-19 05:30:08
Chrome 或其他地方(其他浏览器)中没有“gzip”WebSocket 压缩。
2021-04-22 05:30:08
@oberstet:你确定吗?stackoverflow.com/questions/11646680/...
2021-04-26 05:30:08
gzip 是一种使用 deflate 作为压缩算法文件格式deflate 是 LZ77 和 Huffman 编码的组合。(旧的)每帧压缩 WS 扩展和新的每消息 WS 压缩扩展使用 deflate。
2021-04-27 05:30:08