当前位置: 首页 > 编程日记 > 正文

ProtoBuf格式详解

介绍protobuf编码格式。


protobuf是一种数据交换格式,又称PB编码,由Google开源,类似于Json、XML,但其内部是纯二进制格式,比Json,XML等格式要更精炼,主要用于数据的序列化和反序列化,目前官方提供了JAVA、Python、C++等多种语言的实现。


PB格式的解析依赖于消息文件,在其实现中,.proto定义了各个消息项的id值。


直观地,PB编码就是将一个结构体的内容编码成二进制流。例如一段json数据:

{

"id":176,

 "age":24,

"name":"xieyifenxi",

}


.proto文件的定义如下:

message Person {

required int32 id = 1;

optional int32 age = 2;

required string name = 3;

}

则json数据编码成PB格式则是:

08 b0 01 10 18 1a 0a 78 69 65 79 69 66 65 6E 78 69


通常,在协议解析的过程中碰到的PB编码,是没有.proto文件的,解析的时候,只需要根据数据内容,解析出每一项内容即可,而每一项内容的含义,一般通过分析得到。


在许多APP的数据流中,都会存在protobuf编码。本文将通过对PB编码进行介绍,使大家了解如何在协议分析过程中对其进行解析。


01

数据结构


通过前面的例子,可以看到PB的数据结构就是每项数据独立编码,包含一个表示数据类型wire_type和字段序号field_number的数据头,和对应的数据段内容。即HEAD1+MSG1+HEAD2+MSG2+……


在数据头中,字段的序号field_number在整个数据结构中是唯一的,并且可以乱序、缺失和嵌套,序号是在.proto文件中定义的,协议分析中关心的意义不是很大。


数据类型wire_type则表示数据段内容是什么类型,在protobuf官网上描述了类型的含义:

https://developers.google.com/protocol-buffers/docs/encoding


常见的数据类型wire_type02,分别为Varint类型和Length-delimited变长度数据类型,掌握了这两个类型,基本上在协议解析中,处理PB编码就基本没有障碍了。Varint类型一般就是int数据,而Length-delimited变长度数据类型通常就是字符串数组等数据。


数据头中数据类型和字段序号的组合方式是:(field_number << 3) | wire_type

当然,field_number是Varint类型,需遵循Varint的编码规则。


例如,文首的例子中,id、age、name对应的编码值为:

1 <<< 3 | 0 =0x08

2 <<< 3 | 0 = 0x10

3 <<< 3 | 2 = 0x1a


数据头之后,是数据段,它包含了被编码的数据,不同类型的数据编码格式不同,后面的章节将介绍对应具体类型的编码方法。


02


Varint


Varint是一种对数字进行编码的方法,将数字编码成不定长的二进制数据,数值越小,编码后的字节越少。


编码规则如下:

每个字节的最高位表示下一字节是否仍然是编码的内容,若最高位为1,则下一字节仍然是编码的数字的一部分,若该位为0,则编码到本字节结束。每个字节的后7位,则由小端表示的数字的二进制值,在高位补0凑齐7的倍数位组成。


例如,数值345,其二进制值为 1 0101 1001,在高位补0后分成两个7位 000 0010和 101 1001,则Varint编码结果为:

1 101 1001 0 000 0010

即0xD9 0x02


对文首的例子,由于id 176的二进制值为1011 0000,每七位编码成一个字节,因此,需要用两个字节来表示:

1011 0000 0000 0001

0xB0 0x01


而age 24的二进制值为 1 1000,则只需要一个字节来表示:

0001 1000

即0x18


前面只是弄明白了int32的Varint编码,对协议解析来说,一般已经够用了,除非这个被编码的数,在取出后需要用其特定的含义来进行计算,因为在PB编码中,还考虑了对负数进行Varint编码


当我们按照同样的逻辑对负数进行Varint编码时,会发现,负数编码后占用的字节会很多,这不太合算,因此ZigZag编码在PB中被使用,使得Varint编码可以用较少的位数来对负数进行编码。


PB编码中提供了sint32和sint64类型,使用ZigZag编码,让所有的负数都使用正数表示,计算方式如下:

sint32:

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

sint64:

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


即:

原始值0,通过计算,得到ZigZag表示值为0;

原始值-1,通过计算,得到ZigZag表示值为1;

原始值1,通过计算,得到ZigZag表示值为2;

原始值-2,通过计算,得到ZigZag表示值为3;

原始值2147483647,通过计算,得到ZigZag表示值为4294967294;

原始值-2147483648,通过计算,得到ZigZag表示值为4294967295。

依此类推


在协议还原中,对一个Varint编码的值,想要知道它表达的是int32,还是sint32,就只有想办法找到其对应的.proto文件才可以。


03


Length-delimited


Length-delimited就是对可变长度的数据,在编码时,将长度和数据编码在一起,类似于TLV结构的LV部分,前面为数据长度,后面为由数据长度决定的数据内容,数据长度采用的是Varint编码。


例如文首的例子里,name的值为"xieyifenxi"的长度为10,则编码为:

0a 78 69 65 79 69 66 65 6E 78 69


其中,0x0a为长度值的Varint编码,之后紧接着的是值的内容。


这相当的简单。




对protobuf编码的详解就介绍到这里了,有疑问,可以联系我,或者上其官网了解。它的官网是https://developers.google.com/protocol-buffers/


640?wx_fmt=jpeg

长按进行关注。





相关文章:

Android studio 第二次作业

作业要求&#xff1a; 作一个显示框里面分成三行 一二行占这个框的1/2 第三行独占1/2 第三行里面分成两列第一列占25%&#xff0c;第二列占75%。 屏幕显示效果 实现步骤&#xff1a; <LinearLayout android:orientation"vertical"注意这里是横向布局 …

Cable master (POJ No.1064)

二分搜索思想&#xff1a;bool C(double x)可以得到长度为x的绳子//#define LOCAL #include<stdio.h> #include<math.h> int const MAX_N10005; int const MAX_M100; double const INF100000000; int N,K; double d[MAX_N],lb,ub; //判断是否满足条件 bool C(doubl…

iOS 11 导致tableview 刷新之后漂移问题

在10 系好好的&#xff0c;在11系统刷新只有就会多一个白块。查询才返现&#xff0c;添加一下代码 完美解决此bugself.mainTableView.estimatedRowHeight 0; self.mainTableView.estimatedSectionHeaderHeight 0; self.mainTableView.estimatedSectionFooterHeight 0;

HTTP协议解析之Cookie

“ Cookie与身份认证。”提到HTTP协议&#xff0c;不可避免地都会牵涉到Cookie&#xff0c;可以说&#xff0c;Cookie作为HTTP的重要组成部分&#xff0c;促进了HTTP协议的发展壮大。HTTP协议如果没有了Cookie&#xff0c;将会是一个无状态&#xff0c;无法便捷地进行用户识别的…

libevent源码深度剖析十一

libevent源码深度剖析十一 ——时间管理 张亮 为了支持定时器&#xff0c;Libevent必须和系统时间打交道&#xff0c;这一部分的内容也比较简单&#xff0c;主要涉及到时间的加减辅助函数、时间缓存、时间校正和定时器堆的时间值调整等。下面就结合源代码来分析一下。 1 初始化…

CentOS 安装Apache

# centOS 安装A M P 环境[参考简书作者,非常感谢&#xff01;&#xff01;&#xff01;](https://www.jianshu.com/p/bc14ff0ab1c7) ## 一 Apache 环境安装 1 安装Apache > yum install httpd2 操作指令一览 > systemctl start httpd //启动apache > systemct…

使用admin lte 碰到访问Google字体的问题

下载了admin lte 的模板&#xff0c;运行的时候&#xff0c;发现很慢&#xff0c;看了一下console,发现adminlte.css里有import google的字体文件&#xff0c;众所周知的原因&#xff0c;无法访问&#xff0c;所以网页很慢&#xff0c;没办法&#xff0c;只能下载到本地了,cnbl…

如何突破DNS报文的512字节限制

“DNS协议大家都应该很熟悉&#xff0c;最近有同学问到如何获得UDP承载的超过512字节的DNS报文&#xff0c;借此机会&#xff0c;我们一起了解下DNS协议与报文长度有关的一些细节。”本文将讨论的是DNS协议在UDP承载时超过512字节的这一细节。在之前的文章里&#xff0c;对DNS协…

Fragment为什么须要无参构造方法

日前在项目代码里遇到偷懒使用重写Fragment带参构造方法来传参的做法&#xff0c;顿生好奇&#xff0c;继承android.support.v4.app.Fragment而又不写无参构造方法不是会出现lint错误编译不通过的咩&#xff1f;仔细追究&#xff0c;原来是这货被加了SuppressLint("ValidF…

CentOS 安装FTP

# 安装FTP * 1 安装命令> yum -y install vsftpd * 2 使用如下命令增加账户&#xff0c;其中 /var/www/html 是我们的 ftp 目录&#xff0c;ftpadmin 为 ftp 用户名。 > useradd -d /var/www/html -s /sbin/nologin ftpadmin * 3 给 ftpadmin 这个用户设置密码 > pa…

HTTP协议中的Range和Content-Range

“ 琢磨HTTP协议的每一个细节。”HTTP协议博大精深&#xff0c;每一个细节都应细细体会。否则&#xff0c;在协议还原的过程中&#xff0c;你会遇到各种问题。今天&#xff0c;本文中将对HTTP协议的Range和Content-Range进行分析。Range和Content-Range是 HTTP/1.1中新增的HTTP…

【HTML5游戏开发】简单的《找不同汉字版》,来考考你的眼力吧

一&#xff0c;准备工作 本次游戏开发需要用到lufylegend.js开源游戏引擎&#xff0c;版本我用的是1.5.2&#xff08;现在最新的版本是1.6.0&#xff09;。 引擎下载的位置&#xff1a;http://lufylegend.googlecode.com/files/lufylegend-1.5.2.rar 引擎API文档&#xff1a;ht…

FTP 命令的使用详解

# 使用Terminal 连接FTP ####Tips: 1 通过!进入本地主机的shell&#xff0c;然后通过exit退出本地主机进入远程服务器shell 2 要把文件下载到哪一个目录 就要先cd 到 哪个目录&#xff0c;再去进行ftp 连接&#xff0c;这样 执行 get 文件 自动下载到目录3 下载的文件的时候…

html 11 内联(行内)

行内元素 <span> 块级元素 <div> <p> <section> <header> <footer> 行内元素&#xff0c;这是高 margin-top margin-bottom 无意义 &#xff0c;无效果&#xff0c;因为它仅仅在行内 &#xff0c;它跳不出行&#xff0c;行多少它就多少。…

宅男抖音某猫协议分析及应用破解

“ 分析传说中的快x&#xff0c;顺便提供破VIP线路及去启动广告方法。”在当今这个由应用市场主导的网络上&#xff0c;流传着一批应用&#xff0c;它们低调又神秘&#xff0c;依赖口碑与独立网站在地下渠道传播&#xff0c;应用市场中从来都找不到它们的身影。这类应用&#x…

AdminLTE的使用

官方文档link1.AdminLTE的必要配置文件<!-- Tell the browser to be responsive to screen width --> <meta content"widthdevice-width, initial-scale1, maximum-scale1, user-scalableno" name"viewport"> <!-- Bootstrap 3.3.5 --> …

Linux sendmail发送邮件失败诊断案例(一)

在新服务器上测试sendmail发送邮件时&#xff0c;发现邮件发送不成功&#xff0c;检查日志文件发现如下错误&#xff08;Notice&#xff1a;由于涉及公司服务器&#xff0c;邮箱等&#xff0c;故下面hostname、邮箱地址等信息使用xxx代替&#xff09; tail -40 /var/log/maill…

CentOS 安装Python3

# 基于Linux的 Python3 环境的安装 最近买了一台centOS 阿里云轻量级服务器 自带Python2 准备安装Python3.6 版本的 ## Step * 1 查看当前版本python 的路径 使用以下命令,以便后面安装完毕 建立软链接 > which python 正常情况下会显示python 路径&#xff0c;例如…

某米浏览器黑名单文件破解

“粗粮系统自带浏览器的网址黑名单提取。”某米手机作为高性价比的代表&#xff0c;比起菊厂及OV厂妹风手机&#xff0c;向来被我高看一眼&#xff0c;毕竟雷布斯也是我等码农的典范&#xff0c;以至于我都买过好几件粗粮的产品。虽然它的各个应用&#xff0c;包括系统&#xf…

函数的四种调用模式.上下文调用.call.apply

闭包:函数就是一个闭包,一个封闭的作用域; 返回函数,要返回多个函数就用一个对象封装一下,立即执行函数return回调函数JS动态创建的DOM,不会被搜索引擎抓取,对SEO不友好./*window的name属性*/function fn(){ console.log(this.name);} fn.call({name:"zhangsan"});//…

IOC和DI(转)

1、IoC(Inversion of Control)控制反转和 DI(Dependency Injection)依赖注入 首先想说说IoC&#xff08;Inversion of Control&#xff0c;控制倒转&#xff09;。这是spring的核心&#xff0c;贯穿始终。所谓IoC&#xff0c;对于spring框架来说&#xff0c;就是由spring来负责…

生成公钥链接github

# 生成公钥 连接Git### 1 检查本机是否有公钥 > cd ~/.ssh### 2 如果有的话 直接使用 不要随便删除电脑公钥 没有的话进行生成 生成如下 id_rsa 是 私钥 id_rsa.pub 是公钥 ### 3 生成公钥命令如下 邮箱是你的邮箱地址 终端会提示输入密码 可以以回车带过 如果设置密码…

精确哈克,以贪婪为基础的欺诈式引流法

“ 一种seo手段探讨。”前一段时间&#xff0c;有朋友在后台留言&#xff0c;让我测评一个网站上的信用卡号码生成器&#xff1a;我兴致勃勃&#xff0c;以为是什么黑科技出现了。打开网站&#xff0c;一股熟悉的wordpress风迎面飘来&#xff0c;伴随着风骚的黑色风味。多点击几…

HTML 基础知识(特殊字符的转义)

1. body、head&#xff08;meta&#xff09; <body></body>标签的常见属性&#xff1a; bgcolor&#xff1a;整个页面的背景&#xff1b;text&#xff1a;设置文本颜色link&#xff1a;设置连接颜色&#xff08;&#xff09;&#xff0c;vlink&#xff1a;已经访问…

1 组件化的了解

组件化 概念:讲一个单一的工程的项目&#xff0c;分解成为各个独立的组件&#xff0c;然后按照某一种方式&#xff0c;任意的组织成一个拥有完整业务逻辑的工程 优势 组件的独立–> 独立编写&#xff0c;独立编译&#xff0c;独立运行&#xff0c;独立测试资源的重用–&g…

WebView通过loadDataWithBaseURL加载本地页面卡死

最近开发遇到一个使用 Android WebView加载本地页面进度条始终卡在20%左右不动的情况。打 Log、抓包发现卡在 WebView对象调用 loadDataWithBaseURL方法。 去网上搜了一下解决方案&#xff0c;stackoverflow上有人说是因为 JELLY_BEAN以上版本没有设置 WebView访问文件的权限导…

微信出现“已停止访问该网页”或“关于潜在的违法或违规内容”怎么办?如何获取被屏蔽的网页的网址?...

点击上方↑↑↑蓝字[协议分析与还原]关注我们今天介绍一个微信使用技巧。微信出现“已停止访问该网页”或“关于潜在的违法或违规内容”怎么办&#xff1f;如何获取被屏蔽的网页的网址&#xff1f;由于微信严格的管控措施&#xff0c;经常会导致一些分享的网址被微信屏蔽&#…

self.navigationController push到指定控制器

1 返回到当前页面上面第三级控制器int idx (int)[[self.navigationController viewControllers]indexOfObject:self]; [self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:(idx -3)] animated:YES];2 //遍…

Google搜索的常用技巧

个人搜索方案 1、选择合适的搜索词&#xff0c;一些行业术语或专家名字可以带来更加高质量的结果。 2、搜索词手动使用空格分隔&#xff0c;先进行第一次搜索&#xff0c;看搜索结果标题是否满足预期&#xff0c;如果不满足&#xff0c;采用更换关键词&#xff0c;添加关键词&a…

hdu 1085 Holding Bin-Laden Captive!

Description We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China! “Oh, God! How terrible! ” Don’t be so afraid, guys. Although he hides in a cave of…