絮絮叨叨:新年的第一篇文章,有人投稿啦~
什么是Protobuf?
Protobuf (Protocol Buffers) 是谷歌开发的一款无关平台,无关语言,可扩展,轻量级高效的序列化结构的数据格式,用于将自定义数据结构序列化成字节流,和将字节流反序列化为数据结构。
故适合在不同应用之间相互通信的数据交换格式,需要定义数据格式的.proto文件,编译后即可解析。支持的 Java、Python、C/C 等多种语言。
Protobuf 的一个重要用途就是在RPC (远程过程调用)协议中作为序列化反序列化工具,例如同样是谷歌开发的 gRPC ,使用了 Protobuf 作为序列化工具。
Protobuf 语法
使用 protobuf 前需要定义一个 .proto 文件,内容表示消息的格式,下面以一个简单的 demo 举例:
//syntax关键词定义使用的是proto3语法版本syntax=”proto3″;//message关键词,标记开始定义一个消息messageStudent{//字段类型名字=唯一标识号stringname=1;int32age=2;}
第一行 syntax 指定了要用 proto 的语法,proto3即为proto3对应的语法。
message 表示消息类型,可以有很多个。其结构与 C 语言结构体很相似
Student 表示消息名称,类似于 C 语言结构体的名称
字段类型:用于表示字段的数据类型,包括 string、int32、uint32、float、double、bool、bytes 等等 ,含义和类型名和 C 语言非常相似。唯一标识号:在消息定义中,每个字段后面都有一个唯一的标识号,标识号是用于消息的二进制格式中识别各个字段。
以上就是 protobuf 最简单的语法。
protobuf-c 的使用
在默认安装的 protobuf 中支持了 C 、java、ptython、rust 众多语言,唯独没有支持 C 语言,在 C 语言中使用 protobuf 需要单独编译安装 protobuf-c。
#protobuf-c需要protobufsudoaptinstallprotobuf-compiler#一键三连安装protobuf-cgitclonehttps://github.com/protobuf-c/protobuf-c.git&&cdprotobuf-c./autogen.sh&&./configuremake-j&&sudomakeinstall
安装完成后,protobuf-c 和其它语言的编译一样,指定需要编译的文件和输出的文件类型即可。
protoc-cdemo.proto–c_out=.
protoc-c 是 .proto C 语言的编译器, –c_out 指定输出的文件类型和输出路径
编译完成后,会在指定的路径生成两个文件:demo.pb-c.c 、demo.pb-c.h ,这两个文件分别为打包和解析消息的代码,其编译完头文件提供了以下方法:
//demo.pb-c.h/*Studentmethods*/voidstudent__init(Student*message);size_tstudent__get_packed_size(constStudent*message);size_tstudent__pack(constStudent*message,uint8_t*out);size_tstudent__pack_to_buffer(constStudent*message,ProtobufCBuffer*buffer);Student*student__unpack(ProtobufCAllocator*allocator,size_tlen,constuint8_t*data);voidstudent__free_unpacked(Student*message,ProtobufCAllocator*allocator);
下面使用这些 API 写一个简单的 demo
#include”demo.pb-c.h”#include<stdio.h>#include<stdlib.h>#include<stdint.h>intmain(){Studentstudent=STUDENT__INIT;void*buffer=NULL;int32_tlen;Student*msg=NULL;//初始化数据student.name=”student”;student.age=28;//打包数据len=student__get_packed_size(&student);buffer=malloc(len);student__pack(&student,buffer);//TODO:发送数据到远端设备//TODO:从远端设备接受数据//解包数据msg=student__unpack(NULL,len,buffer);printf(“studentname:%s,age:%d\n”,msg->name,msg->age);//释放资源student__free_unpacked(msg,NULL);free(buffer);return0;}性能对比
有人简单做了一个各种通用序列化协议技术的对比,在几个比较项中 protobuf 的序列化和反序列化性能都是最优秀的,同时占用的体积却非常小。
https://www.iteye.com/blog/agapple-859052
在 github 上有更详细完整的性能对比:https://github.com/eishay/jvm-serializers/wiki,可进行查看。
嵌入式使用
在了解完 protobuf 的基本使用后,考虑如何在嵌入式设备上使用时,发现 protobuf 很难在一般的小型嵌入式设备上使用。
因为其几百K的代码大小,已经超过不少芯片 Flash 的大小了,但是查找资料时发现了替代品:nanopb 。
nanopb 的使用和 .proto 的语法与 protobuf 一致, 一共三个核心文件,编译后的代码不到 10K,非常适合在在嵌入式环境下使用。当然缺点还是有的,就是用时间换空间,序列化和反序列化时间相对较长,不过比 json 等格式仍然快上不少。
end
爱技术,爱生活
往期推荐
时间片轮询的任务调度
为什么建议少用if语句
X-TRACK 软件架构分析