这篇纯正满足本人的好奇心
我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的 贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。牛顿
写本文的时候,想起高中物理课本的一句话:
我如同是一个在海边游玩的孩子,不断为拾到比通常更润滑的石子或更漂亮的贝壳而欢欣鼓舞,而展示在我背后的是齐全未探明的真谛之海。
那个时候不懂这句话,忙于刷分,现在纯正是为了本人的好奇心而探索一些问题,脑海中又开始复现这句话。本文的问题来自于后面的一篇文章:《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')
总结一下,在计算机中最终一切都是二进制格局,当咱们在数据格式中看到二进制时,咱们能够了解为这种存储构造是高度结构化的 , 读取效率更高,更为紧凑,将数据从新进行布局。