关于Protobuf的理解
什么是Protobuf
官方文档的描述:
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
总结一下:语言无关,平台无关,高效,兼容性好
Proto的使用
proto文件编写的基本规则
定义数据结构
// xxx.proto define xxx message
message xxx{
required string val_1 = 1
// required -> 字段出现次数为严格的1次
optional string val_2 = 2
// optional -> 字段出现次数为0或1次
repeated string val_3 = 3
// repeated -> 字段可以出现任意次
message EmbeddMessage{
int32 int32val = 1
string stringVal = 2
}
optional EmbeddMessage example = 4
}
接口代码生成
# $SRC_DIR .proto 在所的源目录
# --cpp_out 生成 c++ 代码
# $DST_DIR 生成代码的目标路径
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto
编码结构
Varints
每一个字节使用7位来表示数字,最高位表示后面是否还有数据。
从后往前编码,所以也是一种压缩算法,对于越小的数字压缩效果越好
ex1. var num int32 ; num = 10,num的二进制为:
00000000 00000000 00000000 00001010
经过Varints编码后:
00001010
ex2. var num int32 ; num = 300,num的二进制为:
00000000 00000000 00000001 00101100
经过Varints编码后:
10101100 00000010
Zigzag
把符号位挪到最后,剩下的31位各向前一位,如果是负数,将除了符号位以外的所有位取反。
编码目的:尽量减少二进制中的1,方便数据压缩
代码实现:
int int2zigzag(int n){
return (n<<1)^(n>>31);
}
int zigzag2int(int n){
return (((unsignedint)n) >> 1) ^ -(n & 1)
}