由于近期研发的项目框架是通过protobuf进行网络通信的,在此之前从未听说过protobuf,上网搜了一下才知道这个东西竟然还蛮火热的
原来自己这么孤陋寡闻。。场面一度十分尴尬。。。
首先介绍一下protobuf,protobuf是google提供的一个开源序列化框架 ,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持PHP、Java、c++、Python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。
protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。
protobuf的消息格式基本等同于C语言的结构体
他的定义字段格式一般就是:限定修饰符+数据类型+变量名称+序列值(猜的)
限定修饰符 分为三种,分别是
required——必须存在项
optional——可选项
repeated——数组,也是可选项
也就是双方通信必须要有的是required,其他的可有可无,比如我们开发时各种版本迭代,所以大部分数据可以用optional,这样没有这种数据也无不影响通信
数据类型就不多说了 大体和C/C++神马的类似,如 bool int double string等,消息类型为message
至于第四个,我看所有的message结构都是1,2,3,4,所以猜想应该是有关索引偏移量的序列值吧~但也不确定。
例如:一个完整定义的消息结构为
message Girl{
required int32 id = 1;
optional double bust = 2;
optional double waist = 3;
optional double hips = 4;
}
当你创建好了一个含有若干个消息结构的probo文件时,可以用protobuf提供的protoc.exe程序(后文会提到)
生成.h和.cc文件,直接导入工程后就可以使用相关的函数了。其命名方式我是非常非常非常的喜欢,
大家看我之前的代码也会发现我的编码习惯就是喜欢加下划线_,不要跟我提神马命名规范,键盘在手天下我有~!
本宝宝就是愿意各种加_ !!!!
比如说上文的Girl类型,根据子元素生成的相关函数就是set_id等
下面说VS工程导入protobuf的具体步骤
首先下载protobuf源码,需要有vs项目工程的,而protobuf-3.0.0-alpha-3之后的版本均不提供vs的工程
只有cmake版本的,我也不是挑事的人,但是我确实感受到了谷歌对微软深深的恶意。。。
下载地址大家可以到官方https://github.com/google/protobuf/里找
或者下载我的完整工程http://download.csdn.net/download/sm9sun/9810539
不知道是不是我网络的问题,反正我不翻墙是下载不了这个的,翻墙之后5k5k的下载,很烦。。
下载后具体步骤:
一、下载之后打开vsprojects文件夹下的protobuf.sln工程,然后编译生成上文中提到用于生成生成.h和.cc文件的protoc.exe程序和lib库
这里注意,要适配你以后开发版本的vs平台工具集进行编译,不然以后你用lib会不兼容的,比如说报错:
error LNK****: 检测到“_MSC_VER”的不匹配项: 值“1*00”不匹配值“1*00”
二、将include头文件及编译好的lib导入你项目的工程里,这里注意尽量保持include路径,因为生成的.h文件也是取的<google/protobuf/……>
这种,改起来很费劲,开始作为强迫症的我想把Google文件夹移除,结果error数量就爆炸了
三、定义proto文件,就是消息类型 然后把生成的.h和.cc文件导入工程里,如果你选了预编译头,那么.cc会报错,尽量不要改整体的预编译头格式
只修改.cc文件的默认选项即可:右键.cc文件——属性——C/C++——预编译头——选择(不使用预编译头)
四、然后就可以写代码调试了,下面给出测试代码
定义消息类型
proto文本
message Girl{
required int32 id = 1;
optional double bust = 2;
optional double waist = 3;
optional double hips = 4;
}
message Girls{
repeated Girl girl = 1;
}
C++文件
// protobuf_demo_VS2017.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "test.pb.h"
void print(Girls&girls)
{
int size = girls.girl_size();
if (!size)
{
cout << "NULL!" << endl ;
}
for (int i = 0; i<size; i++)
{
cout << girls.girl(i).id() << ',';
cout << girls.girl(i).bust() << ',';
cout << girls.girl(i).hips() << ',';
cout << girls.girl(i).waist() << endl ;
}
cout << endl;
}
int main()
{
//校验协议版本
GOOGLE_PROTOBUF_VERIFY_VERSION;
Girls girls;
//因为add_方式是通过引用对象实现的,所以要定义指针类型
Girl *girl;
for (int i = 0; i < 10; i++)
{
//当使用add_方法时,即会重新定义一个新的girl对象然后加入girls里
girl = girls.add_girl();
girl->set_id(i+1);
girl->set_bust(90+i*0.1);
girl->set_hips(60+ i*0.1);
girl->set_waist(80+ i*0.1);
}
fstream out("output.pb", ios::out | ios::binary | ios::trunc);
girls.SerializeToOstream(&out);
out.close();
//先清空girls,测试读写
girls.Clear();
print(girls);
//从person.pb文件读取数据
fstream in("output.pb", ios::in | ios::binary);
if (!girls.ParseFromIstream(&in)) {
cerr << "ERROR." << endl;
exit(1);
}
print(girls);
system("pause");
return 0;
}
测试截图
完整工程下载地址http://download.csdn.net/download/sm9sun/9810539