Thrift的TCompactProtocol紧凑型二进制协议分析
Posted JavaGarden
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thrift的TCompactProtocol紧凑型二进制协议分析相关的知识,希望对你有一定的参考价值。
Thrift的紧凑型传输协议分析:
用一张图说明一下Thrift的TCompactProtocol中各个数据类型是怎么表示的。
报文格式编码:
bool类型:
一个字节。
如果bool型的字段是结构体或消息的成员字段并且有编号,一个字节的高4位表示字段编号,低4位表示bool的值(0001:true, 0010:false),即:一个字节的低4位的值(true:1,false:2).
如果bool型的字段单独存在,一个字节表示值,即:一个字节的值(true:1,false:2).
Byte类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一个字节的值.
I16类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一至三个字节的值.
I32类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一至五个字节的值.
I64类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一至十个字节的值.
double类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),八个字节的值.
注:把double类型的数据转成八字节保存,并用小端方式发送。
String类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一至五个字节的负载数据的长度,负载数据.
Struct类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),结构体负载数据,一个字节的结束标记.
MAP类型:
一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一至五个字节的map元素的个数,一个字节的键值类型组合(高4位键类型,低4位值类型),Map负载数据.
Set类型:
表示方式一:一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一个字节的元素个数和值类型组合(高4位键元素个数,低4位值类型),Set负载数据.
适用于Set中元素个数小于等于14个的情况。
表示方式二:一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一个字节的键值类型(高4位全为1,低4位值类型),一至五个字节的map元素的个数,Set负载数据.
适用于Set中元素个数大于14个的情况。
List类型:
表示方式一:一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一个字节的元素个数和值类型组合(高4位键元素个数,低4位值类型),List负载数据.
适用于Set中元素个数小于等于14个的情况。
表示方式二:一个字节的编号与类型组合(高4位编号偏移1,低4位类型),一个字节的键值类型(高4位全为1,低4位值类型),一至五个字节的map元素的个数,List负载数据.
适用于Set中元素个数大于14个的情况。
消息(函数)类型:
一个字节的版本,一个字节的消息调用(请求:0x21,响应:0x41,异常:0x61,oneway:0x81),一至五个字节的消息名称长度,消息名称,消息参数负载数据,一个字节的结束标记。
以上说明是基于相邻字段的编号小于等于15的情况。
如果字段相邻编号大于15,需要把类型和编号分开表示:用一个字节表示类型,一至五个字节表示编号偏移值。
阅读到这里,或许会疑问,为什么数值型的值用 “一至五个字节”表示?
原因:对数值进行压缩,压缩算法就是Varint,如下简单的说明一下什么是Varint数值压缩。
Varint数值压缩
一个整数一般是以32位来表示的,存储需要4个字节。
当如果整数大小在256以内,那么只需要用一个字节就可以存储这个整数,这样剩下的3个字节的存储空间空闲。
当如果整数大小在256到65536之间,那么只需要用两个字节就可以存储这个整数,这样剩下的2个字节的存储空间空闲。
当如果整数大小在65536到16777216之间,那么只需要用三个字节就可以存储这个整数,这样剩下的1个字节的存储空间空闲。
当如果整数大小在16777216到4294967296之间,那么需要用四个字节存储这个整数。
这时,Google引入了varint,把表示整数的空闲空间压缩,用这种思想来序列化整数。
这种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。
Varint将数按照7位分段,把一个整数压缩后存储。
Varint 中的每个字节的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。
其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,会用两个字节。
这样就可以实现数值压缩。
采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。
从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。
实现Varint32代码:
1
以上是关于Thrift的TCompactProtocol紧凑型二进制协议分析的主要内容,如果未能解决你的问题,请参考以下文章 |