转载请注明出处:http://blog.csdn.net/manchew/article/details/39494901
这段时间项目上接解到了Protocol Buffers, 目前的项目中被用于网络上传输交通信息,之所以选择Protocol Buffers我觉得是有一定的历史缘由,因为早些时间,移动网络传输带宽不是很高,如果传输大量数据会产生比较严重的lag, 再一个原因是Protocol Buffers不像xml那样在解析字段上面,需要花费很高的代价。说到 这里,可以会一头雾水,下面就来简单介绍一下protocol buffers到底是干什么用的。
Protocol buffers是由Google公司启动的开源项目,并且项目的设计开发编码权权由Google大牛完成,可想而知它的健壮性和效率是不容小看的。起初,Protocol buffers的设计主要被用于Google内部使用来处理协议升级带来的困惑,例如:A模块升级后增加了字段F,如果B模块作为接收者也需要对字段F进行处理,代码上表现为:
if(F1)
{
// handle field F1
}
如果F1字段里面又增加了新的描述F2
if(F1)
{
// handle field F1
if(F2)
{
// handle field F2
}
}
这样的代码显得非常难看,我们希望的情况是,当A模块升级后,要做到向后兼容,那么B模块对A模块中新增的字段忽略掉就可以了。这时Protocol buffers应运而生,也是为什么叫Protocol buffers的原因, 而不叫其它的什么buffers。
说简单点,protocol buffers就是对信息进行序列化,之后用它提供的接口直接操作二进制流,所以效率和性能比起直接解析xml文件来讲要好的多。
Protocol Buffers的使用非常简单,首先我们需要定义.proto文件用来描述Message类型,然后调用Protocol buffers提供的编译工具来生成对应语言的source文件,如果你当前的工作语言是c++,那么编译后会生成类似.pb.h 和.pb.cc的文件,前者是头文件,后者是源文件。接下来只需要在代码中使用它们提供的接口就可以轻松完成字段的存取工具。
说了这么多,我们以一个例子来说明如何正确使用,下面的例子是一个简单的编解码过程,我们会把Message序列化到磁盘中,然后再从磁盘中还原出真实的信息。
- 定义Message的描述文件 .proto
这里定义了名为helloword的消息,它有三个字段,分别为id,str,opt,required表示字段在初始化的时候必须给值,否则会出现错误,optional为可选,可以给值,也可以忽略。package lm 表示在生成代码的时候自动放置到lm的namespace下。package lm; message helloword { required int32 id = 1; required string str = 2; optional int32 opt = 3; }
- 编译自己的Protocol buffers首先,需要到https://developers.google.com/protocol-buffers/docs/downloads去下载编译工具,google提供了linux和windows的工具支持,如果你是在windows工作平台,只需要运行google提供的可执行文件protoc.exe就可以,linux下按照google提供的安装方法也比较容易设置自己的编译环境。编译命令为:protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/dst.proto, 如果你的helloworld.proto放在d:/下,生成的class文件放在e:/下,则你只需要命令行下执行protoc -I=d:/ --cpp_out=e:/ d:/helloworld.proto ,这样在e:/下面就会生成helloworld.pb.cc和helloworld.pb.h文件了。
- 在你的工具中使用编译生成的class文件
include "helloworld.pb.h" … int main(void) { lm::helloworld msg1; msg1.set_id(100); msg1.set_str(“helloworld”); fstream output("./out", ios::out | ios::trunc | ios::binary); if (!msg1.SerializeToOstream(&output)) { cerr << "Faile