一.前言
最近业务出于安全性的考虑,在主推pb传输数据,避免使用json。客户端做一层pb编码,同时通过声明网络权限去隐藏掉http请求响应。
这里我把 pb 和 json 相提并论了,所以你一定也会联想到 xml 吧,他们都是通信协议中的结构化数据存储格式。
安卓 7.0 及其以上进行了安全升级,无法对 https 进行抓包。 需安卓同学手动加入网络安全配置的代码才行。
最常见的 http 代理工具,有 whistle 等。
以 whistle 为例,我们只要开启代理之后,就可以抓到某个http的请求和其响应。
当启动pb编码之后,就算客户端不做隐藏请求,你看到的数据也是 Buffer 格式,人类不可读。
你用 whistle 代理,在请求的body中可以看到一份粗略解码的东西,具备可读性,这是因为 whsitle 自身已经帮你做了简单的解码。但本质还是 Buffer, 只是 whistle 稍微帮你转换了一下,然后展示给你看的。
所以,今天就简单聊聊什么是 pb ,以及 Node如何使用 pb 进行编解码。
二.pb定义
从Wikipedia 上看到的定义是:
ProtocolBuffers(Protobuf)isa freeandopen-source cross-platform data format used to serialize structured data.Itisusefulindeveloping programs to communicatewitheach other over a networkorforstoring data.Themethod involves aninterfacedescription language that describes the structure of some dataanda program that generates source codefromthat descriptionforgeneratingorparsing a stream of bytes that represents the structured data.
简单来说,相比于其他数据格式,protobuf 更轻便高效,因为它基于二进制。
PB比XML小3到10倍,快10到20倍,因它的压缩编码传输数据手段比较先进
PB消息经过序列化后会成为一个二进制数据流,该流中的数据为一系列的 Key-Value 对。
这句话,在后面的实践中你可以看到
三.pb压缩手段
(1)Varint编码
对于int类型,通常需要4个字节。但是实际传输时候,可能用不到。采用 Varint,对于很小的 int32 类型的数字,则可以用1个byte来表示。
即 采用变长编码来存储,对网络传输比较有利。
Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,比如 300,会用两个字节来表示:1010 1100 0000 0010
变长存储的数据每个字节只有低7位表示数值,最高位被当做最高有效位(msb),如果最高位为1表示这个整数还没有完结,为0表示完结。
(2)ZigZag编码
在计算机内,一个负数一般会被表示为一个很大的整数,因为计算机定义负数的符号位为数字的最高位。如果采用 Varint 表示一个负数,那么一定需要 5 个 byte。为此 Google Protocol Buffer 定义了 sint32 这种类型,采用 ZigZag 编码。
ZigZag 编码用无符号数来表示有符号数字,正数和负数交错,这就是 ZigZag 这个词的含义了。
(3)W