目录

 


序列化定义:

就是将对象的状态信息转换为可以存储或传输的形式的过程,说白了,就是将对象以值的形式进行转换成可以存储或者传输的方式。

为什么需要进行序列化?

在不同的进程之间可能会需要进行对象的传递,为了解决在跨平台和跨语言的情况下,模块之间的交互和调用,其实就是为了解决数据传输问题。序列化的目的不是为了加密,而是为了数据的跨平台传输。

序列化的过程

发送端:

原始数据->序列化(编码)->特殊格式的字符串

发送字符串

接收端:

接受数据

特殊格式的字符串->反序列化(解码)->原始数据

对原始数据进行处理

c++中常见的序列化方式

(1)google protobuf

(2)json,其本质是采用“键值对”的方式来描述对象,相对于xml而言,序列化后的数据更加简洁,而且其协议比较简单,解析速度比较快。

(3)xml,具有跨机器,跨语言等特点,当这种标记文档的设计被用来序列化对象的时候,就显得冗长而复杂。

其中后两种的序列化之后的数据都比较大,而protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,详情访问protobuf的google官方网站。

protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

protobuf的优点:
(1)灵活(方便接口更新)、高效(效率经过google的优化,传输效率比普通的XML等高很多);
(2)易于使用;开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。
(3)语言支持;原生支持c++,java,python

protobuf的操作流程

(1)准备数据

(2)创建一个新文件 xxx.proto

  (3)将需要序列化的数据->写入到proto文件

(4)通过命令proto将xxx.proto文件生成一个c++的类

对应一个头文件/源文件

操作命令->在windows终端中:protoc xxx.proto --cpp_out=./

  (5)直接使用这个类

里面有对数据操作的api

读数据api->方法名字 变量名()

写数据api->方法名字:set_变量名(arg)

protobuf的使用举例
// 要序列化的数据
struct Person
{
    int id;
    string name;
    string sex;	// man woman
    int age;
};

int id;
// Info.proto
syntax = "proto3";

message Person
{
    int32 id=1;
    bytes name=2;
    bytes sex=3;
    int32 age=4;    
}

(1)在.proto文件中定义消息格式

// protobuf的版本
syntax = "proto3";	// proto2
// 组织Persion结构体
// 语法格式
message 关键字(相当于被创建出的类的名字)
{
	// 成员变量
	数据类型 变量名 = 变量的编号;	// 编号从1开始, 不能重复
}

// .proto文件 生成 c++ 类的命令
protoc proto文件名 --cpp_out=生成目录

(2)repeated限定修饰符

syntax = "proto3";
message Persion
{
    int32 id = 1;   // 编号从1开始
    bytes name = 2;
    string sex = 3;
    int32 age = 4;
}
// 要求name有多个 -> 数组
syntax = "proto3";
message Persion
{
    int32 id = 1;   // 编号从1开始
    // vector<string> name;
    repeated bytes name = 2;	// name可以在程序中创建多个, 在程序中作为动态数组来使用
    string sex = 3;
    int32 age = 4;
}

(3)枚举

syntax = "proto3";
// 定义枚举
enum Color
{
	Red = 0;	// protbuf中第一个枚举值必须为0
	Green = 6;
	Blue = 9;
}
message Persion
{
    int32 id = 1;   // 编号从1开始
    bytes name = 2;
    string sex = 3;
    int32 age = 4;
    Color color = 5;	// 枚举变量
}

(4)proto文件的导入

// Persion.proto
syntax = "proto3";
// 导入另外一个proto文件
import "Info.proto";

enum Color
{
	Red = 0;	// protbuf中第一个枚举值必须为0
	Green = 6;
	Blue = 9;
}

message Persion
{
    int32 id = 1;   // 编号从1开始
    repeated bytes name = 2;
    string sex = 3;
    int32 age = 4;
    Color color = 5;
    Info info = 6;	// Info对象, 导入的proto文件中的类
}

(5)包 -> 命名空间

// Persion.proto
syntax = "proto3";
// 导入另外一个proto文件
import "Info.proto";
// 添加命名空间
package itcast;	// Persion类属于itcast这个命名空间

enum Color
{
	Red = 0;	// protbuf中第一个枚举值必须为0
	Green = 6;
	Blue = 9;
}

message Persion
{
    int32 id = 1;   // 编号从1开始
    repeated bytes name = 2;
    string sex = 3;
    int32 age = 4;
    Color color = 5;
    // 命名空间.类名
    itheima.Info info = 6;	// Info对象, 导入的proto文件中的类
}
// Info.proto
syntax = "proto3";
// Persion类属于itheima这个命名空间
package itheima;

message Persion
{
    bytes address = 1;  // 地址
    int32 number = 2;   // 门牌号
}

(6)使用protobuf编译器生成C++类

# protobuf编译器, 编译源码得到的 protoc.exe
# 语法
# --cpp_out 生成的c++类的位置
protoc.exe xxx.proto --cpp_out=目录

(7)vs配置 -> 添加宏

在项目属性->c/c++->预处理器->预处理器定义中添加PROTOBUF_USE_DLLS