Android开发经验谈程序员手机移动程序开发

Protocol Buffer (二)原理篇

2017-01-04  本文已影响0人  MagicCoder

上一篇文章简单地描述了一下Protocol Buffer的用法,懂得了上篇文章的用法之后,相信大家正常使用Protocol Buffer已经没有太大问题了,没有覆盖到的细节用法,在网上搜一下应该也不难找到。然而知其表而复知其理,知其华而复知其实,所以今天这篇文章给大家介绍一下Protocol Buffer的一些编码原理,可以用来解释为什么序列化之后的数据包比XML和JSON小那么多。

一、Varint编码
Protocol Buffer 在对数字进行编码使用的是Varint的编码方式。我们使用的int类型,一般需要占用4个字节的长度,采用Varint编码,可以用一个字节或多个字节来表示一个数字,值越小的数字占用越少的字节数。

Varint的每个byte的最高位bit用来表示后续的byte是不是也属于该数字的一部分。如果最高位为0,则表示该byte是这个数字的最后一个byte,如果最高位为1,表示后面的一个byte仍然是该数字的一部分。以无符号数为例,对于0-127,只需要一个字节表示,最高位为0,后7位表示值。如果一个数字需要多个字节去表示,这里面有个需要注意的地方:高位的数字是放在后面的字节里面的。

example:300的Varint编码为1010 1100,0000 0010,去掉两个最高位为010 1100,000 0010,将后面的字节放到前面为000 0010 010 1100,也就是100101100,换算成十进制就是300了。

对于有符号的数字,Protocol Buffer 还会采用ZigZag编码,这样无论正数还是负数,绝对值小的时候使用Varint编码占用的字节数就会更少。ZigZag编码大家从下面一张图就可以看明白原理了。

ZigZag编码.png

二、消息体编码
我们平时用JSON传递数据,Java对象序列化为JSON串之后一般会是下面这个样子。

{"code":200,"name":"magiccoder","sex":"man","index":"www.magiccoder.net"}

可能平时一直这么用,大家都已经习以为常了,但是这个对象的数据包在频繁传输的过程中,key值其实是一直重复传输的,key值仅仅是一个标志位,只要客户端和服务端约定之后采用同样的key值就可以,如果把key值直接约定为从1开始的自然数,肯定是比上面的JSON串的长度要短的。甚至我们可以这么想,把需要传输的字段值按照约定的顺序排列下来,做好字段之间的分界,就连key值都不需要了。

Protocol Buffer使用的是Tag-Length-value的形式来组织数据的,Length字段非必需。

三、Protocol Buffer 的其他优点
笔者认为Protocol Buffer除了数据包小,序列化和反序列化速度快,还有下面两个很不错的优点:

附上官方网站,上面介绍的还是很全面的,英文还不错的同学可以看一下:
https://developers.google.com/protocol-buffers/

2017年第一周,最近玩的太high了,所以过了这么久才更新这篇文章。
最后祝大家2017年身体健康、工作顺利、心想事成、笑口常开~

上一篇 下一篇

猜你喜欢

热点阅读