protobuf篇:介绍、安装、测试

也有proto3,都可以吧,我最开始接触的是2,就翻译 2 吧。

官网地址:https://developers.google.cn/protocol-buffers/docs/proto,有兴趣的朋友可以自行查阅。

好吧,建议自己打开看,我不全翻译,就看到一些觉得比较重要的我搬过来。

Protobuf消息定义

你首先需要在一个 .proto 文件中定义你需要做串行化的数据结构信息。每个ProtocolBuffer信息是一小段逻辑记录,包含一系列的键值对。

消息由至少一个字段组合而成,类似于C语言中的结构。每个字段都有一定的格式。

字段格式:限定修饰符① | 数据类型② | 字段名称③ | = | 字段编码值④ | [字段默认值⑤]

这里有个非常简单的 .proto 文件定义了个人信息:

message Person {

required string name=1;

required int32 id=2;

optional string email=3;

enum PhoneType {

MOBILE=0;

HOME=1;

WORK=2;

}

message PhoneNumber {

required string number=1;

optional PhoneType type=2 [default=HOME];

}

repeated PhoneNumber phone=4;

}

①限定修饰符

Required: 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。

Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。—因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。

Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。

②数据类型速查

Protobuf定义了一套基本数据类型。几乎都可以映射到C++\Java等语言的基础数据类型.

在这里插入图片描述

  1. N 表示打包的字节并不是固定。而是根据数据的大小或者长度。

  2. 关于message,类似于C语言中的结构包含另外一个结构作为数据成员一样。

④字段编码值

编码值的取值范围为 1~2^32(4294967296)。

不信往上面翻翻看,看看是不是都是数值。

其中 1~15的编码时间和空间效率都是最高的,编码值越大,其编码的时间和空间效率就越低(相对于1-15),当然一般情况下相邻的2个值编码效率的是相同的,除非2个值恰好实在4字节,12字节,20字节等的临界区。比如15和16.

1900~2000编码值为Google protobuf 系统内部保留值,建议不要在自己的项目中使用。

protobuf 还建议把经常要传递的值把其字段编码设置为1-15之间的值。

消息中的字段的编码值无需连续,只要是合法的,并且不能在同一个消息中有字段包含相同的编码值。

⑤默认值。

当在传递数据时,对于required数据类型,如果用户没有设置值,则使用默认值传递到对端。当接受数据是,对于optional字段,如果没有接收到optional字段,则设置为默认值。


几个注意事项

import

protobuf 接口文件可以像C语言的h文件一样,分离为多个,在需要的时候通过 import导入需要的文件。

虽然可以在单个.proto文件中定义多种消息类型(例如消息,枚举和服务),但当在单个文件中定义大量具有不同依赖性的消息时,也

可能导致依赖性膨胀。建议每个.proto文件包含尽可能少的消息类型。

关于package

避免名称冲突,可以给每个文件指定一个package名称,对于C++解析为名称空间。

记得在开头加上这两句:

syntax = “proto3”;

package demo;

关于enum

枚举的定义和C++相同,但是有一些限制。

  1. 枚举值必须大于等于0的整数。

  2. 使用分号(;)分隔枚举变量而不是C++语言中的逗号(,)


编译PB


可编译文件

首先,你要有一个PB文件可以拿去编译,我知道你多半也没有,没事我这里有。

syntax = “proto3”;

package demo;

message Person {

string name = 1;

int32 id = 2;

string email = 3;

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

string number = 1;

PhoneType type = 2;

}

repeated PhoneNumber phone = 4;

}


开始编译

我下载了好多款,不过主语言是C++,毕竟打开一次不容易。打不开下载目录的小伙伴可以私信我拿。

打开cmd, cd到该目录,protoc.exe的命令行参数格式如下:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto

在这里插入图片描述

编译之后就会出现新的文件了。

阅览文件

打开之后太长了,自己去看。我这里提几点。

(1)proto中的package在C++中是namespace;

(2)proto中的message在C++中是class,类里面有各个成员的set/get;基类是google::protobuf::Message。

(3)代码中可以看见C++11中的移动构造和移动赋值函数。


搞技术的人不搞那些弯弯绕的,放码过来吧。

放码过来


proto

syntax = “proto2”;

package tutorial;

message Person {

optional string name = 1;

optional int32 id = 2;

optional string email = 3;

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

optional string number = 1;

optional PhoneType type = 2 [default = HOME];

}

repeated PhoneNumber phones = 4;

}

message AddressBook {

repeated Person people = 1;

}


读.cpp

#include

#include

#include

#include “person.pb.h”

using namespace std;

// This function fills in a Person message based on user input.

void PromptForAddress(tutorial::Person* person) {

cout << "Enter person ID number: ";

int id;

cin >> id;

person->set_id(id);

cin.ignore(256, ‘\n’);

cout << "Enter name: ";

getline(cin, *person->mutable_name());

cout << "Enter email address (blank for none): ";

string email;

getline(cin, email);

if (!email.empty()) {

person->set_email(email);

}

while (true) {

cout << "Enter a phone number (or leave blank to finish): ";

string number;

getline(cin, number);

if (number.empty()) {

break;

}

tutorial::Person::PhoneNumber* phone_number = person->add_phones();

phone_number->set_number(number);

cout << "Is this a mobile, home, or work phone? ";

string type;

getline(cin, type);

if (type == “mobile”) {

phone_number->set_type(tutorial::Person::MOBILE);

} else if (type == “home”) {

phone_number->set_type(tutorial::Person::HOME);

} else if (type == “work”) {

phone_number->set_type(tutorial::Person::WORK);

} else {

cout << “Unknown phone type. Using default.” << endl;

}

}

}

// Main function: Reads the entire address book from a file,

// adds one person based on user input, then writes it back out to the same

// file.

int main(int argc, char* argv[]) {

// Verify that the version of the library that we linked against is

// compatible with the version of the headers we compiled against.

GOOGLE_PROTOBUF_VERIFY_VERSION;

if (argc != 2) {

cerr << “Usage: " << argv[0] << " ADDRESS_BOOK_FILE” << endl;

return -1;

}

tutorial::AddressBook address_book;

{

// Read the existing address book.

fstream input(argv[1], ios::in | ios::binary);

if (!input) {

cout << argv[1] << “: File not found. Creating a new file.” << endl;

} else if (!address_book.ParseFromIstream(&input)) {

cerr << “Failed to parse address book.” << endl;

return -1;

}

}

// Add an address.

PromptForAddress(address_book.add_people());

{

// Write the new address book back to disk.

fstream output(argv[1], ios::out | ios::trunc | ios::binary);

if (!address_book.SerializeToOstream(&output)) {

cerr << “Failed to write address book.” << endl;

return -1;

}

}

// Optional: Delete all global objects allocated by libprotobuf.

google::protobuf::ShutdownProtobufLibrary();

return 0;

}


写.cpp

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!


写.cpp

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-BSzCWViw-1715875811738)]

[外链图片转存中…(img-QWY73Gdr-1715875811739)]

[外链图片转存中…(img-ol5Si6yr-1715875811739)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值