网络-数据序列化之protobuf

原创 2015年07月01日 15:44:41

很多时候需要将一些数据打包,就是把这些数据搞在一起,方便处理。最常见的情况就是把需要传输的数据,当然数据不止一条,打包成一个消息,然后发送出去,接收端再以一定的规则接收并恢复这些数据。这称为数据序列化以及反序列化。

可能以前最容易想到的简单方式就是把数据存在一个结构体里面,然后把结构体作为消息发送出去,但是后来呢大家都用的是XML、或者是JSON的数据格式来传输,这样处理数据比较方便。

当然这里介绍的protobuf也是一种数据传输格式,它是google的一个开源项目,官方源码下载(点击打开链接)。不同于XML、JSON等的数据格式,protobuf直接将用户数据序列化成了二进制数据,这从本质上决定了它的性能优势,也是目前大家选择它的一个重要原因,特别是当对传输效率要求较高的情况下,protobuf也就成为不二的选择了。关于它们性能的对比分析详见这篇文章(点击打开链接)。


下面简单介绍protobuf的用法:

首先protobuf是一套库,目前支持c++、java、python三种语言,这里以c++的用法为例,并且版本使用目前最新的2.6.1。

1、windows平台下

首先,需要编写.proto文件,这个就相当于是需要传输的消息模板,类似于上面的结构体、XML文件等,它定义着需要传输的数据本身。下面是一个简单的例子data.proto。

package data;

message user
{
	required int32 id = 1;
	required string name = 2;
}


下一步,由于.proto文件并不能直接传输,也不能直接使用,所以还需要将其转化成其它形式。这一步需要下载protobuf的一个编译器protoc.exe,可以去官方下载,其作用就是将.proto文件转换成.pb.h.文件和.pb.h文件,也就是常规的c++头文件和源文件。接下来看如何使用protoc.exe生成c++文件,假如protoc.exe和data.proto在同一个文件目录下的话,那么只需要在当前目录下运行cmd命令:protoc --cpp_out=. ./data.proto,即可当前目录生成需要的c++文件data.pb.h和data.pb.cc。



最后一步,就是如何在具体的项目工程中使用了。先用vs建立一个c++项目,然后将data.pb.h和data.pb.cc导入工程,然后在main函数中引入data.pb.h头文件,便可以在main函数中使用刚刚定义的消息了,比如下面的简单使用。

int main()
{
	// 序列化数据
	data::user test1;
	test1.set_id(1);
	test1.set_name("YJ");
	std::string str;
	test1.SerializeToString(&str);

	// 反序列化数据
	data::user test2;
	test2.ParseFromString(str);
	cout << test2.id() << " " << test2.name() << endl;
	return 0;
}
如果就这样尝试编译,那么会报错,各种头文件不存在,所以还需添加文件,打开下载好的protobuf源码,找到/src目录下的google文件夹,将其拷到工程目录下,不必导入工程,然后在工程属性中附加包含目录中包含google文件夹所在的目录即可。


继续尝试编译,编译通过,但是紧接着出现链接错误,无法解析的外部符号,原因是函数只有声明没有实现,所以还需要链接protobuf的静态库。先打开protobuf的源码,进入目录protobuf-2.6.1.zip\protobuf-2.6.1\vsprojects,打开vs工程文件,然后右击生成解决方案,然后在/debug目录下找到生成的lib文件,将他们拷入前面的工程目录下,最后在工程属性中附加库目录即可。


最后一步就是链接该库文件,在man函数前面加上下面两句代码。

#pragma comment(lib, "libprotobuf.lib")
#pragma comment(lib, "libprotoc.lib")

现在编译运行工程,输出下面的结果,说明使用protobuf进行数据的序列化和反序列化都可以正常进行。



2、其他平台的使用

protobuf是可以跨平台的,关键问题就是如何生成各个平台下的库文件,如windows下.lib文件,android下的.a文件等。

具体的编译生成方式以后再补充,这里就直接给打包好的,各个平台下的库文件,以及需要的头文件(点击打开链接),版本均为2.6.1,参见前面windows下的使用进行包含、引用、链接即可。



最后附上一篇关于protobuf的不错的文章(点击打开链接),如果对它还不是很明白,可以去看看。


httpclient +protobuf 实现数据传输

最近项目要接入某联盟广告,采用protobuf作为传输协议,以前没弄过,这次刚好使用到了,整理下 一、环境准备:(mac下) 1.1 下载protobuf2.5安装包 ...

将数据序列化有什么作用

1.序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。 序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中...
  • yhd0916
  • yhd0916
  • 2017年02月14日 10:24
  • 326

Java序列化与反序列化

Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨。  1.Java序列化与反序列化  Java序列化是指把Java对象转换为...

为什么要使用序列化

在日常的程序开发中,用到了很多次的序列化的数据,可是一直不清楚为什么要将数据序列化,经过一段时间的学习与验证,有了一些个人看法,在这里做个总结,权当抛砖引玉了。...

protobuf序列化/反序列化性能及问题

为了tensorflow项目要求测试protobuf序列化/反序列化的性能,测试过程及测试结果如下: 一. 测试环境 python 2.7 + proto3 二. 测试方法 1. 自定义一个prot...

(转)C++ 版本的protobuf 动态序列化方法

这篇文章要解决的问题是:在接收到 protobuf 数据之后,如何自动创建具体的 Protobuf Message 对象,再做的反序列化。“自动”的意思是:当程序中新增一个 protobuf Mess...

【protobuf 001】 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)

转载:http://www.cnblogs.com/lanxuezaipiao/p/3703988.html 导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C+...

我对C++ string和length方法的一个长期误解------从protobuf序列化说起(没处理好会引起数据丢失、反序列化失败哦!)

自认为C和C++基础知识还行, 于是以为下面程序的结果都是3, 看看: #include #include using namespace std; int main() { char szT...
  • stpeace
  • stpeace
  • 2016年11月05日 18:54
  • 2126

使用protoBuf进行序列化和反序列化

import com.dyuproject.protostuff.LinkedBuffer; import com.dyuproject.protostuff.ProtobufIOUtil; impo...
  • mggwct
  • mggwct
  • 2016年12月22日 10:19
  • 924

google_protobuf数据类型

要通信,必须有协议,否则双方无法理解对方的码流。在protobuf中,协议是由一系列的消息组成的。因此最重要的就是定义通信时使用到的消息格式。   Protobuf消息定义 消息由至...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:网络-数据序列化之protobuf
举报原因:
原因补充:

(最多只允许输入30个字)