proto2

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化,适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

字段规则

  • required: 字段必须存在
  • optional: 字段没有或有一个
  • repeated: 字段重复,0个或多个

proto 数据类型

.proto Type
Notes
C++ Type
Java Type
Python Type[2]
Go Type
double 固定8字节长度 double double float *float64
float 固定4字节长度 float float float *float32
int32 可变长度编码。对负数编码低效,如果字段可能是负数,用sint32代替 int32 int int *int32
int64 可变长度编码。对负数编码低效,如果字段可能是负数,用sint64代替 int64 long int/long[3] *int64
uint32 可变长度编码,无符号整数 uint32 int[1] int/long[3] *uint32
uint64 可变长度编码,无符号整数 uint64 long[1] int/long[3] *uint64
sint32 可变长度编码。有符号整数。 These more efficiently encode negative numbers than regular int32s. int32 int int *int32
sint64 可变长度编码。有符号整数。These more efficiently encode negative numbers than regular int64s. int64 long int/long[3] *int64
fixed32 固定4字节长度,无符号整数。 More efficient than uint32 if values are often greater than 228. uint32 int[1] int/long[3] *uint32
fixed64 固定8字节长度,无符号整数。 More efficient than uint64 if values are often greater than 256. uint64 long[1] int/long[3] *uint64
sfixed32 固定4字节长度,有符号整数 int32 int int *int32
sfixed64 固定8字节长度,有符号整数 int64 long int/long[3] *int64
bool   bool boolean bool *bool
string UTF-8 encoded or 7-bit ASCII text. string String str/unicode[4] *string
bytes 包含任意字节序列 string ByteString str []byte

编码规则

1.varints

理解简单protobuf编码,首先要知道varints。varints使用一个字节或多个字节对整数序列化方法。

varints中的每个字节除了最后一个字节,有一个最有效位(most significant bit ,msb),这意味指示之后有其他字节。每个字节的低7位一组数的补码

例如:

1

0000  0001

300

1010  1100  0000  0010

只取每个字节低七位

010  1100  000  0010

小端序->大端序

000  0010  010  1100 -->  0001  0010  1100  =300

2.消息结构

protobuf 消息是一系列key-value对,对于二进制消息,字段数字作为关键字。字段的命名和类型在解码时确定。

在进行消息编码时,key/value被连接成字节流。在解码时,解析器可以直接跳过不识别的字段,这样就可以保证新老版本消息定义在新老程序之间的兼容性,从而有效的避免了使用older消息格式的older程序在解析newer程序发来的newer消息时,一旦遇到未知(新添加的)字段时而引发的解析和对象初始化的错误。最后,我们介绍一下字段标号和字段类型是如何进行编码的。每一个 wire-format消息的key实际上是有两个值组成:proto文件中定义的字段标号和wire type。

Type
Meaning
Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimited string, bytes, embedded messages, packed repeated fields
3 Start group groups (deprecated)
4 End group groups (deprecated)
5 32-bit fixed32, sfixed32, float

key = (field_number << 3) | wire_type key的最后3个bits用于存储字段的类型信息。那么在使用该编码时,Protocol Buffer所支持的字段类型将不会超过8种。

例如:150(十进制) 在protobuf二进制文件中是 08 96 01

08 --> 00001000  field_number=1,wire_type=0

96 01 -> 1001 0110  0000 0001 -->  001 0110   000  0001  -->  000 0001   001  0110   --> 1001  0110 =150

3.Signed Integers

wire_type=0 的类型都以varint 进行编码,所以对于int32和int64,对于负数使用补码,int32 需要5个字节,int64需要10个字节,有符号整数使用ZIgZag编码

ZigZag 将有符号整数映射到无符号整数,以此得到一个绝对值较小的数字(例如-1)j就可以获得一个较小的varint编码值。

Signed Original
Encoded As
0 0
-1 1
1 2
-2 3
2147483647 4294967294
-2147483648 4294967295

sint32:       (n << 1) ^ (n >> 31)

sint64:       (n << 1) ^ (n >> 63)

4.Non-varint Numbers

wire-type=1:fixed64, sfixed64, double 固定64bit

wire-type=5:fixed32, sfixed32, float,固定32bit

5.Strings

wire-type=2,字符串长度使用varint编码

例如

message Test2 {
optional string b = 2;
}

b=“testing” ,编码后结果:

12 07 74 65 73 74 69 6e 67

12: field number=2,wire-type=2  (2<< 3)|2=0x12

长度为7 varint编码 0x07

74 65 73 74 69 6e 67  UTF8 编码

6.Embedded Messages嵌套消息

wire-type=2
message Test1 {
optional int32 a = 1;
}
message Test3 {
optional Test1 c = 3;
}

Test1's a field set to 150

Test3 编码结果: 1a 03 08 96 01

1a: field_number=3,wire_type=2  (3<< 3)|2=11010=0x1a

03: 字节数

08 96 01 : c编码结果

7.Optional And Repeated Elements

proto2 :消息被定义repeated (没有 [packed=true]选项),编码的消息有0或多个使用相同字段标号的key-value对,这些重复的值不必连续出现; 他们可能会与其他字段交错,但在解码时顺序保留

optional字段,编码后的消息可能有也可能没有包含该字段号的键值对。

proto3 使用packed encoding:

包含零个元素的打包重复字段不会出现在编码消息中。这个字段的所有元素都打包到一个wire-type=2的key-value对中

message Test4 {
repeated int32 d = 4 [packed=true];
}
22        // key (field number 4, wire type 2)
06 // payload size (6 bytes)
03 // first element (varint 3)
8E 02 // second element (varint 270)
9E A7 05 // third element (varint 86942) proto2默认不设置 packed=true
repeated编码采用空格(0x20)分隔
结果是20 03 20 8e 02 20 9e a7  05

protobuf编码的更多相关文章

  1. protobuf 编码实现解析(java)

    一:protobuf编码基本数据类型 public enum FieldType { DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ), FLOAT (Java ...

  2. go protobuf 编码与解码

    package main import ( "encoding/hex" "fmt" "github.com/golang/protobuf/prot ...

  3. protobuf中的编码规则

    protobuf中的编码规则 (1)序列化和反序列化: 在开始本部分的内容之前,首先有必要介绍两个基本概念,一个是序列化,一个是反序列化.这两个概念的定义在网上搜一下都很多的,但大多都讲得比较晦涩,不 ...

  4. google protocol buffer——protobuf的使用特性及编码原理

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们展示了 ...

  5. google protocol buffer——protobuf的编码原理二

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们主要通 ...

  6. Protobuf使用规范分享

    一.Protobuf 的优点 Protobuf 有如 XML,不过它更小.更快.也更简单.它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍.你可以定义自己的数据结构 ...

  7. protobuf学习(2)-相关学习资料

    protobuf官方git地址 protobuf官方英文文档   (你懂的需要FQ) protobuf中文翻译文档 protobuf概述          (官方翻译 推荐阅读) protobuf入门 ...

  8. Cocos2d-JS/Ajax用Protobuf与NodeJS/Java通信

    原文地址:http://www.iclojure.com/blog/articles/2016/04/29/cocos2d-js-ajax-protobuf-nodejs-java Google的Pr ...

  9. Protobuf C#教程 ThriftC#教程大合辑

    android与PC,C#与Java 利用protobuf 进行无障碍通讯[Socket] http://www.cnblogs.com/TerryBlog/archive/2011/04/23/20 ...

随机推荐

  1. Magento 2开发教程 - 创建新模块

    视频在youtube网站国内访问不了,可以使用FQ软件查看. 视频地址:www.youtube.com/embed/682p52tFcmY@autoplay=1 下面是视频文字介绍: Magento ...

  2. java爬取百度首页源代码

    爬虫感觉挺有意思的,写一个最简单的抓取百度首页html代码的程序.虽然简单了一点,后期会加深的. package test; import java.io.BufferedReader; import ...

  3. 【Hadoop系列】linux下 root用户免密码登录远程主机 ssh

    SSH原理:[Hadoop系列]linux SSH原理解析 操作环境: CentOS 6.5 操作对象: 用户A主机和远程主机B 正文部分:斜体加粗代表linux指令. linux下 非root用户免 ...

  4. element ui tabl 输出Html

    在使用element ui的表格的时候有遇到过表格中的数据需要换行的问题,数据是由后台传回的包含分隔符的字符串,在尝试过使用slot和直接输出html后并不能实现 解决方法:使用column的form ...

  5. Python基础学习总结(六)

    8.函数 函数是带名字的代码块,用于完成具体的工作.def函数定义,指出函数名.定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参 ...

  6. java.lang.UnsupportedClassVersionError: action/Login : Unsupported major.minor version 52.0 (unable to load class action.Login)异常

    用myeclipse新建一个web项目,用了struts2框架,tomcat启动的时候报了这个错误. 我的问题原因是tomcat7的运行环境不知道为什么设置成了myeclipse1.7的jre,我给它 ...

  7. python 之 os._exit() sys.exit() 、exit()

    sys.exit 执行该语句会直接退出程序,这也是经常使用的方法,也不需要考虑平台等因素的影响,一般是退出Python程序的首选方法. 退出程序引发SystemExit异常,(这是唯一一个不会被认为是 ...

  8. Docker问题集合

    1. 安装后启动出现 解决办法: 删除以下文件夹重新启动docker服务即可: 可能原因:(1) 之前docker进程出现错误并保存在keys.json文件中 (2) 删除之前配置了阿里云镜像,生成了 ...

  9. JavaScript中的attachEvent和addEventListener

    attachEvent和addEventListener在前端开发过程中经常性的使用,他们都可以用来绑定脚本事件,取代在html中写obj.onclick=method. 相同点: 它们都是dom对象 ...

  10. 02HTML-<img>

    一.img的属性:alt/title alt属性是替换名字,是给搜索引擎抓取使用,当图片显示不出来时,就会显示出alt的内容: title 属性是提示文字,当鼠标移到图片上的时候会显示出来,大部分的标 ...