类似于json的一种数据格式,独立于语言,而且是二进制方式,所以比json更快,而且还可以直接存储一些图、树
持久化(存到磁盘硬盘)领域中,数据存到磁盘叫序列化,从磁盘读取出来叫反序列化 网络传输领域中,数据块转字符串叫序列化,对端把字符串解析为数据块叫反序列化
比如一个结构体三个数据依次发送出去,接收端可能一下接收了三个,是无法处理的(不知道边界) 第二种情况,一次性发送出去,添加标记,这样接收端可以一次性解封装,常采用TLV (Tag Length Value)
类似于刚刚说的TLV结构,是一种组织数据的格式,可以把若干数据组织成一块---> 序列化为字符串 --> 发送 --> 字符串被反序列化 --> 解析数据
只演示Linux下的安装过程
https://github.com/protocolbuffers/protobuf/releases/tag/v21.12
我这里下载的21.12版本,比较老了,但是基本功能都能用
先上传到Linux上,一般的ssh工具如Mobaxterm都有这个功能
tar -zxvf your_protobuf_package.tar.gz -C /path/to/you_want
cd /path/to/you_want
./configure
make
sudo make install
protoc --version
test.proto
[root@hcss-ecs-9452 test_proto]# cat test.proto /*struct Person{ string name; string sex; int age;}*/syntax = "proto3";message Person{ string name = 1; bytes sex = 2; int32 age = 3;}
[root@hcss-ecs-9452 test_proto]# cat test.proto
/*
struct Person
{
string name;
string sex;
int age;
}
*/
syntax = "proto3";
message Person
string name = 1;
bytes sex = 2;
int32 age = 3;
protoc ./test.proto --cpp_out=./
[root@hcss-ecs-9452 test_proto]# [root@hcss-ecs-9452 test_proto]# lstest.proto[root@hcss-ecs-9452 test_proto]# protoc ./test.proto --cpp_out=./[root@hcss-ecs-9452 test_proto]# lstest.pb.cc test.pb.h test.proto[root@hcss-ecs-9452 test_proto]#
[root@hcss-ecs-9452 test_proto]#
[root@hcss-ecs-9452 test_proto]# ls
[root@hcss-ecs-9452 test_proto]# protoc ./test.proto --cpp_out=./
test.pb.cc test.pb.h test.proto
节选test.pb.h ,这部分就是protobuf给出的对name这个数据的处理方式,比如清空 设置 查询 根据地址修改等
enum : int { kNameFieldNumber = 1, kSexFieldNumber = 2, kAgeFieldNumber = 3, }; // string name = 1; void clear_name(); const std::string& name() const; template <typename ArgT0 = const std::string&, typename... ArgT> void set_name(ArgT0&& arg0, ArgT... args); std::string* mutable_name(); PROTOBUF_NODISCARD std::string* release_name(); void set_allocated_name(std::string* name); private: const std::string& _internal_name() const; inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name();
enum : int {
kNameFieldNumber = 1,
kSexFieldNumber = 2,
kAgeFieldNumber = 3,
};
// string name = 1;
void clear_name();
const std::string& name() const;
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_name();
PROTOBUF_NODISCARD std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
std::string* _internal_mutable_name();
这里需要注意,protobuf大量使用c++11特性,但是centOS默认安装的是g++4.8.5编译器,可能不支持,需要在编译选项中-std=gnu++11
# 目标文件TARGET = run# 源文件SRC = run.cpp test.pb.cc# 编译器CC = g++# 编译选项CFLAGS = -I. -lprotobuf -std=gnu++11# 默认规则all: $(TARGET)# 依赖关系$(TARGET): $(SRC) $(CC) $(CFLAGS) $^ -o $@# 编译.proto文件生成C++源文件和头文件test.pb.cc test.pb.h: test.proto protoc --cpp_out=. $<# 清理规则clean: rm -f $(TARGET) test.pb.cc test.pb.h# 防止make删除中间文件.PHONY: all clean
# 目标文件
TARGET = run
# 源文件
SRC = run.cpp test.pb.cc
# 编译器
CC = g++
# 编译选项
CFLAGS = -I. -lprotobuf -std=gnu++11
# 默认规则
all: $(TARGET)
# 依赖关系
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $^ -o $@
# 编译.proto文件生成C++源文件和头文件
test.pb.cc test.pb.h: test.proto
protoc --cpp_out=. $<
# 清理规则
clean:
rm -f $(TARGET) test.pb.cc test.pb.h
# 防止make删除中间文件
.PHONY: all clean
可能要先设置一下环境变量
echo $LD_LIBRARY_PATH# 如果已经设置过/usr/local/lib就不用往下走了echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib' >> ~/.bashrcsource ~/.bashrcecho $LD_LIBRARY_PATH
echo $LD_LIBRARY_PATH
# 如果已经设置过/usr/local/lib就不用往下走了
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib' >> ~/.bashrc
source ~/.bashrc
[root@hcss-ecs-9452 test_proto]# lsMakefile run.cpp test.pb.cc test.pb.h test.proto[root@hcss-ecs-9452 test_proto]# makeg++ -I. -L/user/local/lib -lprotobuf -std=gnu++11 run.cpp test.pb.cc -o run[root@hcss-ecs-9452 test_proto]# ./runname:Jacksex:女age:18
Makefile run.cpp test.pb.cc test.pb.h test.proto
[root@hcss-ecs-9452 test_proto]# make
g++ -I. -L/user/local/lib -lprotobuf -std=gnu++11 run.cpp test.pb.cc -o run
[root@hcss-ecs-9452 test_proto]# ./run
name:Jack
sex:女
age:18
新增一个proto文件,后续步骤和上面一致
[root@hcss-ecs-9452 test_proto]# cat testComplex.proto syntax = "proto3";message Addr{ int32 door_num = 1; bytes addr = 2;}message Person{ repeated string name = 1; bytes sex = 2; int32 age = 3; Addr ad = 4;}
[root@hcss-ecs-9452 test_proto]# cat testComplex.proto
message Addr
int32 door_num = 1;
bytes addr = 2;
repeated string name = 1;
Addr ad = 4;
[root@hcss-ecs-9452 test_proto]# cat run.cpp#include "testComplex.pb.h"int main(){ Person p1; p1.add_name(); p1.set_name(0, "Jack"); p1.add_name("Tom"); p1.add_name("sb"); p1.set_sex("女"); p1.set_age(18); p1.mutable_ad()->set_addr("陕西省西安市雁塔区"); p1.mutable_ad()->set_door_num(999); std::string output; p1.SerializeToString(&output); Person p2; p2.ParseFromString(output); //std::cout << "name:" << p2.name() << std::endl; std::cout << "sex:" << p2.sex() << std::endl; std::cout << "age:" << p2.age() << std::endl; std::cout << "addr:" << p2.ad().addr() << p2.ad().door_num() << "号" << std::endl; int size = p2.name_size(); for(int i = 0; i < size; ++i) { std::cout << "第" << i << "个名字是" << p2.name(i) << std::endl; } return 0;}
[root@hcss-ecs-9452 test_proto]# cat run.cpp
#include "testComplex.pb.h"
int main(){
Person p1;
p1.add_name();
p1.set_name(0, "Jack");
p1.add_name("Tom");
p1.add_name("sb");
p1.set_sex("女");
p1.set_age(18);
p1.mutable_ad()->set_addr("陕西省西安市雁塔区");
p1.mutable_ad()->set_door_num(999);
std::string output;
p1.SerializeToString(&output);
Person p2;
p2.ParseFromString(output);
//std::cout << "name:" << p2.name() << std::endl;
std::cout << "sex:" << p2.sex() << std::endl;
std::cout << "age:" << p2.age() << std::endl;
std::cout << "addr:" << p2.ad().addr() << p2.ad().door_num() << "号" << std::endl;
int size = p2.name_size();
for(int i = 0; i < size; ++i)
std::cout << "第" << i << "个名字是" << p2.name(i) << std::endl;
return 0;
[root@hcss-ecs-9452 test_proto]# cat testComplex.proto syntax = "proto3";enum Color{ red = 0; //第一个必须是0 green = 5; //后面的不必123 blue = 6;}message Addr{ int32 door_num = 1; bytes addr = 2;}message Person{ repeated string name = 1; bytes sex = 2; int32 age = 3; Addr ad = 4; Color color = 9; //这里也可以不写567}[root@hcss-ecs-9452 test_proto]# cat run.cpp#include "testComplex.pb.h"int main(){ Person p1; p1.add_name(); p1.set_name(0, "Jack"); p1.add_name("Tom"); p1.add_name("sb"); p1.set_sex("女"); p1.set_age(18); p1.mutable_ad()->set_addr("陕西省西安市雁塔区"); p1.mutable_ad()->set_door_num(999); p1.set_color(Color::red); std::string output; p1.SerializeToString(&output); Person p2; p2.ParseFromString(output); //std::cout << "name:" << p2.name() << std::endl; std::cout << "sex:" << p2.sex() << std::endl; std::cout << "age:" << p2.age() << std::endl; std::cout << "addr:" << p2.ad().addr() << p2.ad().door_num() << "号" << std::endl; int size = p2.name_size(); for(int i = 0; i < size; ++i) { std::cout << "第" << i << "个名字是" << p2.name(i) << std::endl; } std::cout << "Color:" << p2.color() << std::endl; return 0;}
enum Color
red = 0; //第一个必须是0
green = 5; //后面的不必123
blue = 6;
Color color = 9; //这里也可以不写567
p1.set_color(Color::red);
std::cout << "Color:" << p2.color() << std::endl;
import "/path/xxx.proto"
package xxx
当其他proto文件调用时: xxx.Person p
xxx.Person p
上述命令会转换为cc文件的namespace
原文链接:https://www.cnblogs.com/xsl-blogs/p/18223922
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728