C++实现RPC分布式网络通信框架(四)-------关于protobuf

我们在编写网络应用程序的时候需要注意codec(编解码器),因为数据在网络中传输的都是二进制字节码数据,而我们拿到的目标数据往往不是字节码数据。因此在发送数据时就需要编码,接收数据时就需要解码。
codecd的组成部分有两个:decoder(解码器)和encoder(编码器)。encoder负责把业务数据转换成字节码数据,decoder负责把字节码数据转换成业务数据。我们要介绍的protobuf就是一个编解码器。

一、Protobuf

protobuf 是Google发布的开源项目,全称Google protocol buffers ,是google 的一种数据交换的格式,它独立于平台语言。特点如下:
1.支持跨平台、多语言(支持绝对多数语言,Java 、c++、c#、python等),每一种实现都包含了相应语言的编译器以及库文件。
2.高性能、高可靠性
3.使用protobuf 编译器能自动生成代码,protobuf 是将类的定义换成 .proto 文件进行描述,然后通过protoc.exe 编译器 编译成对应的语言文件
4.由于它是一种二进制的格式,比使用 xml(20倍) 、json(10倍)进行数据交换快许多。可以把它用 于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数 据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

二、protobuf下载及安装

github源代码下载地址:https://github.com/google/protobuf 源码包中的src/README.md,有详细的安装说明,安装过程如下:
1、解压压缩包:unzip protobuf-master.zip
2、进入解压后的文件夹:cd protobuf-master
3、安装所需工具:sudo apt-get install autoconf automake libtool curl make g++ unzip
4、自动生成configure配置文件:./autogen.sh
5、配置环境:./configure
6、编译源代码(时间比较长):make
7、安装:sudo make install
8、刷新动态库:sudo ldconfig

三、protobuf应用实践

1.创建test.proto文件:.proto是protobuf文件的标准后缀名
2.编写protobuf文件

syntax = "proto3";//声明了protobuf的版本
package rpcpr; //声明代码所在的包(对于C++来说是namespace)

//定义登陆请求消息类型,name,pwd
message LoginRequest
{
    
    
    string name=1;
    string pwd=2;
}
//登陆响应消息类型
message LoginResponse
{
    
    
    int32 errcode=1;
    string errmsg=2;
    bool success=3;
}

3.生成protobuf文件:protoc test.proto --cpp_out=./
(1)使用protoc来进行编译.proto文件,指定语言类型为c++,输出路径为./
(2)生成了test.pb.cc和test.pb.h文件
(3)对.proto文件中定义的message和service都会抽象成类,从对应的父类中继承而来,而该类又会被公有继承生成新的stub类,生成对应的成员变量和成员方法,这些可以进入生成的.pb.h和.pb.cc查看。
4.编辑C++文件并编译

#include"test.pb.h"
#include<iostream>
#include<string>
using namespace rpcpr;//proto文件编译后生成的名称空间,需要使用其中的变量
int main()
{
    
    
    LoginRequest req;//根据生成的cc文件定义类对象
    req.set_name("zhangsan");//使用编译生成的成员方法添加成员变量
    req.set_pwd("123456");//使用编译生成的成员方法添加成员变量
    std::string send_str;//用于存储序列化后的信息
    if(req.SerializeToString(&send_str))
    //调用序列化方法来序列化字符串,成功则执行以下代码
    {
    
    
        std::cout<<send_str<<std::endl;
    }
    //从send_str反序列化一个login请求对象
    LoginRequest reqB;
    if(reqB.ParseFromString(send_str))//调用成员方法来反序列化字符串
    {
    
    
        std::cout<<reqB.name()<<std::endl;//输出反序列化后的信息
        std::cout<<reqB.pwd()<<std::endl;
    }
    return 0;
}

g++ main.cc test.pb.cc -lprotobuf//会生成编译后的可执行文件

四、改进

在定义字符时,一般不会将其定义成string,而是将其定义为bytes型,多字节型,适合存储,否则需要进行多次的转码编码。不过接收时他还是会生成string型,所以生成的方法基本没有什么差别。

五、json和protobuf的优缺点

1.json存储数据的键值对,而protobuf直接存储数据,等大小的protobuf和json文件protobuf存储的数据更多,更节省空间;
2.protobuf基于二进制存储,json基于文本存储,所以效率更高,占用资源更少;
3.protobuf不仅可以存储类型数据,还提供了抽象的类;
4.学习protobuf比学习json麻烦一些,萝卜青菜各有所爱,所以选择合适的即可。

猜你喜欢

转载自blog.csdn.net/qq_45132647/article/details/107718628