博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Protobuf学习
阅读量:6869 次
发布时间:2019-06-26

本文共 1627 字,大约阅读时间需要 5 分钟。

     公司现在大部分协议都使用protobuf的格式,protobuf协议数据冗余数据小、序列化和反序列化速度快,但它序列化的数据在传输过程中是不可理解的(不像xml或jason那样抓到了包就可以直接看到数据内容)。

     通过对protobuf的C++源码及python源码的一番简单阅读后,发现protobuf的序列化其实是个比较简单的过程。protobuf将数据分为6大类:

                          

        序列化后的数据,保存了每个字段的field_id、数据类型、数据内容(wiretype_length_delimited类型的数据还包含了一个数据内容的长度信息)这三个信息。field_id就是定义proto文件时,对每个字段定义的id数字,例如

           message Test {

                   fixed32 fixed32_id = 16;

            }

这个结构体中变量fixed32_id的field_id为2。一个字段序列化的格式如下:

           

浅绿色方块的内容只有当该字段的数据类型为wiretype_length_delimited时才有。可以看到序列化的数据分为三个数据块,field_id和数据类型放在同一个数据块中,数据长度在一个数据块中,数据内容放在一个数据块中。

        数据类型只有6种,3个bit就足够表示了,所以第一个数据块中数据的内容为:data1 = (filed_id << 3)  | (0x7 & 数据类型枚举值)。为了节约空间,protobuf并不是直接将data1写入到buffer中,而是采用了类似utf8的编码方式,每个byte只有后7个bit写数据,第一个bit用来表示下一个byte是否还属于这个数据块。例如:上述的Test结构体,只有一个字段,数据类型是wiretype_fiexed32,那么该字段的第一个数据块的内容则是 (16 << 3 ) | (0x7 & 5) =  0x85, 7个bit表示不了,所以至少需要两个byte, 第一个byte的值为 ((0x85 & 0x7f) | 0x80) = 0x85,第二个byte的值为 (0x85 >> 7) = 0x1。所以这里第一个数据块的数据就是两个字节:

             

由于uint32_id这个字段是wiretype_fiexed32类型,所以没有数据长度这个信息,数据内容是直接将fixed32_id这个字段的值按照32位整数的形式写入buffer,例如将结构体中fixed32_id赋值为1,则该结构体序列化后的数据为:

             

类似,如果数据类型是wiretype_fiexed64,则降数据按照64位整数的形式写入buffer。如果数据类型wiretype_varint,则数据内容的写入方式与第一个数据块类似,每个byte的第1个bit用来标志该数据是否结束,所以这里个人认为对于追求执行速度的程序,数据可以定义为fixed32、sfixed32、fixed64、sfixed64、float、double,这样序列化和反序列化省去”编码”过程,提高了执行速度,但对于存储和带宽是瓶颈的程序可以考虑将数据定义为int32、int64、uint32、uint64、sint32、sint64、bool、enum类型,类型对应表如下:

          

wiretype_length_delimited的数据比较特殊,它可以存放string、数组还可以存放一个自定义的message。当存放string类型的数据长度的数据块存放的是string的长度,数据内容数据块存放string的原始信息;当存放message的时候,数据长度的数据块存放的是message序列化为buffer后的长度,数据内容数据块存放message序列化为buffer后的内容。数据长度的写入方式跟wiretype_varint数据内容的写入方式一致。

 

参考:

转载于:https://www.cnblogs.com/hualisuzhou/p/4126820.html

你可能感兴趣的文章
在git 创建了一个项目
查看>>
Catnut 微博app第一个版本发布了
查看>>
Cocos Creator常见问题汇总
查看>>
String MVC 异常处理
查看>>
[G[DI]-CS-ML.RL012] Universal Reinforcement Learning
查看>>
为采集动态网页安装和测试Python Selenium库
查看>>
method.invoke源码分析
查看>>
创业公司的研发架构:规范化研发流程
查看>>
ubuntu jdk 环境变量配置
查看>>
用freeswitch架构自己的VOIP网络电话
查看>>
《虚拟机并发编程》读书笔记(二)关于STM
查看>>
游戏修改记录
查看>>
全栈工程师特写
查看>>
页面点击其他位置,目标标签都隐藏
查看>>
WordPress主题教程(三):HTML静态模板制作
查看>>
C#游戏编程之创建一个简单的卷轴射击游戏
查看>>
varnish 4.0 官方文档翻译5-varnish概况
查看>>
阿里云漏洞提示:phpMyAdmin <=4.8.1 checkPageValidity函数缺陷可导致GETSHELL
查看>>
pyCharm中python对象的自动提示问题
查看>>
一些常用JavaScript方法的重写 持续更新中
查看>>