一. 介绍
MQTT是一种轻量级的通信协议,用于在物联网设备和服务器之间传输消息。它具有低带宽、低功耗和开销小的特点,适用于资源有限的设备。
protobuf是一种数据序列化的格式,是Google开发的一种高效的结构化数据存储格式。它可以将数据转化成二进制格式,以便在网络中传输。protobuf可以提供多种语言的支持,并能快速地解析和编码数据。
在实际应用中,MQTT和protobuf可以结合使用。通常情况下,MQTT用于在物联网设备和服务器之间传输消息,而protobuf用于对传输的数据进行序列化和反序列化。
当物联网设备向服务器发送消息时,可以使用protobuf将数据序列化为二进制格式,然后通过MQTT协议传输给服务器。服务器接收到消息后,可以使用protobuf将二进制数据反序列化为可读的数据格式,以便进行进一步的处理和分析。
通过使用protobuf,可以有效地压缩数据并减少传输的开销,在资源受限的物联网设备中尤为重要。同时,使用MQTT作为传输协议,可以确保可靠的消息传输和高效的通信。因此,在实际应用中,MQTT和protobuf可以互相配合使用,提供高效的物联网通信解决方案。
protobuf3的文档
还有参考文章
Protobuffer是将结构化的数据序列化,更小更快,依赖编译生成的相应的头文件和源文件。
在定义字段的时候,需要唯一确定,而且范围为1~15的字段编号需要⼀个字节进⾏编码,16 ~ 2047内的数字需要两个字节进⾏编码。编码后的字节不仅只包含了编号,还包含了字段类型。所以1~15要⽤来标记出现⾮常频繁的字段,要为将来有可能添加的、频繁出现的字段预留⼀些出来。
19000~19999不可⽤是因为:在Protobuf协议的实现中,对这些数进⾏了预留。如果⾮要在.proto⽂件中使⽤这些预留标识号,例如将name字段的编号设置为19000,编译时就会报警:
Protobuf的功能,在ros的msg中,例子中设置了mask用来分辨哪一个小组件需要被控制,但是在protobuf中,每一个变量都有一个has_xxx方法来判断协议中有没有填写某个字段,这样就能够确定要更改的地方,从而不再需要mask来指定了。
has_xxx
函数用于protobuf中的optional字段,用于检查一个optional字段是否已被设置。"xxx"对应的是你要检查的字段的名称。
比如,你有一个protobuf消息定义如下:
message Test {
optional int32 result = 1;
optional string msg = 2;
}
那么你可以用has_result()
和has_msg()
函数来检查result和msg字段是否被设置。
使用示例:
Test t;
if (t.has_result()) {
// `result`字段已被设置
int32 res = t.result();
}
if (t.has_msg()) {
// `msg`字段已被设置
string message = t.msg();
}
几个关键字
在proto2中
Require
表示必须有 optional
是可选 repeated
是可以有多个
在proto3中 没有require
默认都是optional repeated
不变
Option是一个选项,
option (url) = "/developer/clean_module_control";
它的请求应该发送到“/dev…”这个url
Protobuf中,只有msg才能够被has_xxx
调用
Repeated是可重复字段,类似于数组。
在protobuf中mutable函数通常用于获取消息字段的指针或者引用,使得我们可以修改此字段的值。
Person person;
person.mutable_name()->assign("John");
如果子字段是原字段的一项,设置的时候就要
set_allocated_xxx
回调函数
if(!app.CreateSubscriber<HelloWorld>(std::bind(
&SubscriberComponent::LogMsg, this, std::placeholders::_1
)))
表明是这个函数this的LogMSG函数,传入参数是一个。
获取robot
Robot.xxx()
Robot.has_xxx()
Robot_mutable_xxx()获取指向这个xxx的指针,可以嵌套第一种用法来访问子字段
Robot.clear_xxx() 或者清除所有robot.clear()
向repeat字段添加Robot.add_xxx()
统计robot.xxx_size()
Robot.release_xxx()获取使用权并自己管理内存
Robot.set_allocated_xxx 将管理权交还给proto
对于repeated的对象,robot.mutable_xxx()-Add().set_xxx
二、 Protobuf 优点
性能好/效率高
时间维度:采用XML格式对数据进行序列化时,时间消耗上性能尚可;对于使用XML格式对数据进行反序列化时的时间花费上,耗时长,性能差。
空间维度:XML格式为了保持较好的可读性,引入了一些冗余的文本信息。所以在使用XML格式进行存储数据时,也会消耗空间。
整体而言,Protobuf以高效的二进制方式存储,比XML小3到10倍,快20到100倍。
代码生成机制的优点
首先,代码生成机制能够极大解放开发者编写数据协议解析过程的时间,提高工作效率;其次,易于开发者维护和迭代,当需求发生变更时,开发者只需要修改对应的数据传输文件内容即可完成所有的修改。
代码生成机制
代码生成机制的含义
在Go语言中,可以通过定义结构体封装描述一个对象,并构造一个新的结构体对象。比如定义Person结构体,并存放于Person.go文件:
type Person struct{
Name string
Age int
Sex int
}
在分布式系统中,因为程序代码时分开部署,比如分别为A、B。A系统在调用B系统时,无法直接采用代码的方式进行调用,因为A系统中不存在B系统中的代码。因此,A系统只负责将调用和通信的数据以二进制数据包的形式传递给B系统,由B系统根据获取到的数据包,自己构建出对应的数据对象,生成数据对象定义代码文件。这种利用编译器,根据数据文件自动生成结构体定义和相关方法的文件的机制被称作代码生成机制。
支持“向后兼容”和“向前兼容”
向后兼容:在软件开发迭代和升级过程中,"后"可以理解为新版本,越新的版本越靠后;而“前”意味着早起的版本或者先前的版本。向“后”兼容即是说当系统升级迭代以后,仍然可以处理老版本的数据业务逻辑。
向前兼容:向前兼容即是系统代码未升级,但是接受到了新的数据,此时老版本生成的系统代码可以处理接收到的新类型的数据。
支持前后兼容是非常重要的一个特点,在庞大的系统开发中,往往不可能统一完成所有模块的升级,为了保证系统功能正常不受影响,应最大限度保证通讯协议的向前兼容和向后兼容。
支持多种编程语言
Protobuf不仅仅Google开源的一个数据协议,还有很多种语言的开源项目实现。在Google官方发布的Protobuf的源代码中包含了C++、Java、Python三种语言。
三、Protobuf 缺点
可读性较差
为了提高性能,Protobuf采用了二进制格式进行编码。二进制格式编码对于开发者来说,是没办法阅读的。在进行程序调试时,比较困难。
缺乏自描述
诸如XML语言是一种自描述的标记语言,即字段标记的同时就表达了内容对应的含义。而Protobuf协议不是自描述的,Protobuf是通过二进制格式进行数据传输,开发者面对二进制格式的Protobuf,没有办法知道所对应的真实的数据结构,因此在使用Protobuf协议传输时,必须配备对应的proto配置文件