共计 3188 个字符,预计需要花费 8 分钟才能阅读完成。
这篇纯正满足本人的好奇心
我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的 贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。牛顿
写本文的时候,想起高中物理课本的一句话:
我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。
那个时候不懂这句话,忙于刷分,现在纯正是为了本人的好奇心而探索一些问题,脑海中又开始复现这句话。本文的问题来自于后面的一篇文章:《HTTP 学习笔记 (三) HTTP/2》,这篇文章里咱们提到了 HTTP/ 2 的几个特点:
- is binary, instead of textual
二进制代替了文本
- is fully multiplexed, instead of ordered and blocking
多路复用
- can therefore use one connection for parallelism
并行申请
- uses header compression to reduce overhead
压缩申请头,缩小耗费
- allows servers to“push”responses proactively into client caches
容许服务器被动推送响应进入客户端的缓存中
其实对于 1 我是不了解的,毕竟在计算机的世界都是“二进制”嘛,过后我的想法是难道是跟 JDK 解决 String 一样的操作,在 JDK8 之前,String 自身是借助于 char 来存储的:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];}
到了 JDK 8 之后, JDK 借助 byte 来存储字符串:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
@Stable
private final byte[] value;}
毕竟一个 char 占两个字节, 一个 byte 只占一个字节,因为我之前用程序连贯过充电桩,接管充电桩的报文,给的报文都是 byte 类型的,byte 更小,像 String 就带了一些额定的信息,所以我猜测,是这个意义上的二进制,然而这只是猜测,我想过用抓包工具去验证我的猜测,然而发现抓包工具我用的并部署,再加上 HTTP/2.0 都是加密报文,抓包挺麻烦的,我也想过看 HTTP Client 的源码,然而这两个奏效都太慢了,最近偶尔翻看 MongDB 的文档,翻到了这方面的阐明,这个问题就有了答案。其实 HTTP 也对下面的二进制进行了解释:
Why is HTTP/2 binary?
Binary protocols are more efficient to parse, more compact“on the wire”, and most importantly, they are much less error-prone, compared to textual protocols like HTTP/1.x, because they often have a number of affordances to“help”with things like whitespace handling, capitalization, line endings, blank lines and so on.
二进制协定绝对于文本协定,比方 HTTP/1.x,解析效率、传输效率更高,有更好的容错性。还提供了一些机制能够帮忙解决空白字符、大小写、空行等等。
For example, HTTP/1.1 defines four different ways to parse a message; in HTTP/2, there’s just one code path.
例如,HTTP/1.1 定义了四种解析数据的形式,然而在 HTTP/2, 只有一种代码门路。
It’s true that HTTP/2 isn’t usable through telnet, but we already have some tool support, such as a Wireshark plugin.
尽管 HTTP/ 2 曾经不能再应用 Telnet 了,然而咱们也有其余工具的反对,比方 Wireshark plugin。
所以 HTTP 说本人是二进制的,潜台词是 HTTP/ 2 的数据包采取了高度结构化的格局,因为在计算机中,最终一切都是二进制模式存在。在 HTTP/ 2 中传输的数据会被格式化为帧 (frame), 每个帧都会被调配一个流。HTTP/ 2 的帧具备特定的格局,如下图所示:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
在 HTTP/ 2 中,每个帧都由两局部组成: 帧头 (9 个字节),帧头是固定长度的,占据 9 个字节,蕴含了对于该帧的一些信息,比方长度、类型等。帧头前面是有效载荷,长度可变,取决于帧的类型和内容。这有点相似于 TCP 数据包,读取 HTTP/ 2 帧能够遵循定义好的过程 (先读取数据长度,而后帧的类型)。相比之下,HTTP/1.1 是由一个 ASCII 编码的文本行组成的非结构化格局,尽管这些文本最终将以二进制模式传输,然而基本上它是一串字符的流,而不是明确地被分为独立的帧。
HTTP/1.1 的音讯通过一一字符地读取字符来解析,直到达到换行字符为止,这种形式有点凌乱,然而因为无奈晓得每行的长度,所以必须一一字符进行解决。对于 HTTP 注释的长度能够提前晓得,咱们能够在 HTTP 头里获知到这个信息。
这让我想起了 MongDB 的 BSON,我想 BSON 中的 binary 的语义该当和 HTTP/ 2 的 binary 语义是对等的,在 BSON 标准的官网能够看到咱们的猜测是正确的:
BSON is a binary format in which zero or more ordered key/value pairs are stored as a single entity. We call this entity a document.
BSON 是一种二进制格局,其中有零个或多个有序的键 / 值对被存储为一个繁多的实体,咱们将这个实体称之为文档。
上面是一个 JSON 和其对应的 BSON 格局的示例:
{"hello": "world"} →
\x16\x00\x00\x00 // total document size 总的文档大小 算上大小字段自身
\x02 // 0x02 = type String
hello\x00 // field name 字段值
\x06\x00\x00\x00world\x00 // field value 字段值
\x00 // 0x00 = type EOO ('end of object')
总结一下,在计算机中最终一切都是二进制格局,当咱们在数据格式中看到二进制时,咱们能够了解为这种存储构造是高度结构化的 , 读取效率更高,更为紧凑,将数据从新进行布局。