首页 > 其他分享 >protocol buffer 基础

protocol buffer 基础

时间:2023-11-03 10:38:25浏览次数:43  
标签:info protocol proto buffer 基础 phone message foo id

我们知道接口传输数据的格式有XML,它是 web services 使用的传输数据的格式,在web services 中叫 WSDL。

https://www.w3school.com.cn/wsdl/index.asp

不过 web Services 已经是被淘汰的技术了。

现在更是主流的是使用JSON作为数据传输格式。HTTP + JSON是黄金搭档。

什么是protocol buffer

protocol buffer是一种与语言和平台无关。

Protocol Buffer是用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。

protocol buffer 是如何使用

  • 定义 xx.proto文件,即 接口数据格式。
  • 使用 proto 命令生成对应语言脚本。
  • 通过语言脚本设置接口要发送/接收的数据。

定义 .proto 文件,

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

这里定义一个简单的 foo.proto 文件定义了个人信息:

syntax = "proto2";
package info;

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;
}

这个信息就是你的接口要发送的数据格式。

文件说明:

syntax = "proto2";

文件最开始建议说明使用proto2还是proto3语法的声明。

package info;

文件必须以 package xxxx; 声明开头,作为协议唯一的标识,避免不同项目的命名冲突,你可以理解成我给一个人起名叫张三,如果要想找这个人,就要叫一声张三。

message Person {
    ...
    message PhoneNumber {
        ...
    }
}

一个 message 相当于一个指定类型的集合,例如 bool, int32, float, double ,string 这些类型都是可以直接使用在proto协议中的某个message当中指定数据类型的。

一个message可以直接嵌套另一个message使用,被嵌套的message就相当于string一样,被认为是一种数据类型。

required string name=1;
required int32 id=2;
optional string email=3;
...
repeated PhoneNumber phone=4;

每个message的字段必须要声明是requiredrepeatedoptional

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

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

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

好了,你现在对 .proto 文件的定义有了大概的一个了解了。

使用 proto 命令生成对应语言脚本

1、下载 protobuf 文件

https://github.com/protocolbuffers/protobuf/releases

以windows为例,下载下面两个文件:

  • protobuf-python-3.12.3.zip
  • protoc-3.12.3-win64.zip

2、 先解压 protobuf-python-3.12.3.zip 文件,得到 protobuf-3.12.3目录,再解压 protoc-3.12.3-win64.zip 文件得到 protoc 目录,把你 protoc 目录放到 protobuf-3.12.3目录。

3、 设置环境变量path

D:\pybase\protobuf-3.12.3\protoc\bin

将上面的路径添加环境变量。

4、 执行 proto 命令,生成python脚本。利用前面创建 foo.proto 文件。

protoc --python_out=. foo.proto

你会看到同目录下多出一个 foo_pb2.py 的文件。不用打开看了,反正你也看不懂。

通过语言脚本设置接口要发送/接收的数据

现在我们利用 foo_pb2.py 文件定义发送的接口数据。 创建一个test_foo_pb2.py文件。

import foo_pb2


def set_info(info_):
    info_.id = 1
    info_.name = "tom"
    info_.email = "[email protected]"

    phone = info_.PhoneNumber
    phone.phone = 400100
    phone.type = 2

    return info_


info = foo_pb2.Person()

one_info = set_info(info)
print("设置数据:\n", one_info)

proto_info = one_info.SerializeToString()
print("序列化:\n", proto_info)


def get_info(wanted_info):
    """
    反序列化的数据
    """
    print("反序列化:\n")
    wanted_id = wanted_info.id
    print("info id:", wanted_id)
    print("his age: ", wanted_info.name)

    print("his phone number :", wanted_info.PhoneNumber.phone)
    print("his phone type :", wanted_info.PhoneNumber.type)


first_parsed = foo_pb2.Person()
first_parsed.ParseFromString(proto_info)
get_info(first_parsed)

打印结果:

设置数据:
 name: "tom"
id: 1
email: "[email protected]"

序列化:
 b'\n\x03tom\x10\x01\x1a\[email protected]'
 
反序列化:
info id: 1
his age:  tom
his phone number : 400100
his phone type : 2

我帮你问:这有什么用?

想想当你在发送数据的时候,以 序列化的数据发送,是不是更节省资源?是不是更安全?

标签:info,protocol,proto,buffer,基础,phone,message,foo,id
From: https://blog.51cto.com/fnngj/8162013

相关文章

  • 同步机与无功功率等基础
     发电机功率因数超前是指什么是吸收无功功率还是指发出容性无功功率?还是?https://zhidao.baidu.com/question/460958728.html发电机功率因数超前是指在电网吸收无功功率。当励磁电流较大时,电压较高,定子电流I滞后与端电压,输出滞后的无功功率,这时发电机运行在“过励”状态;逐步减......
  • 【专题】中国汽车基础软件发展白皮书4.0报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=34132自18世纪中期工业革命以来,人类进入工业社会。在历次工业革命中,人类通过发明创造和管理革新,改进生产方式、降低成本、提高效率,随之而来的是生活、物质、文化、教育等各方面的变化,人际关系和社会结构也得以重塑。如今,数字化技术的发展为工业注入......
  • 09Go语言基础之函数
    函数是组织好的、可重复使用的、用于执行指定任务的代码块。本文介绍了Go语言中函数的相关内容。函数Go语言中支持函数、匿名函数和闭包,并且函数在Go语言中属于“一等公民”。函数定义Go语言中定义函数使用func关键字,具体格式如下:func函数名(参数)(返回值){函数体}......
  • 08Go语言基础之map
    Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。mapmap是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。map定义Go语言中map的定义语法如下:map[KeyType]ValueType其中,KeyType:表示键的类型。ValueType:表示键对应的值的类......
  • 12Go语言基础之结构体
    Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。类型别名和自定义类型自定义类型在Go语言中有一些基本的数据类型,如string、整型、浮点型、布尔等数据类型,Go语言中可以使用type关键......
  • 16Go语言基础之接口
    接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。接口本章学习目标了解为什么需要接口以及接口的特点掌握接口的声明和使用掌握接口值的概念掌握空接口的特点及其使用场景在Go语言中接口(interface)是一种类型,一种抽象的类型。相较于......
  • Go语言基础之error接口
    Go语言中的错误处理与其他语言不太一样,它把错误当成一种值来处理,更强调判断错误、处理错误,而不是一股脑的catch捕获异常。Error接口和错误处理Error接口Go语言中把错误当成一种特殊的值来处理,不支持其他语言中使用try/catch捕获异常的方式。Error接口Go语言中使用一个......
  • 【scipy 基础】--傅里叶变换
    傅里叶变换是一种数学变换,它可以将一个函数或信号转换为另一个函数或信号,它可以将时域信号转换为频域信号,也可以将频域信号转换为时域信号。在很多的领域都有广泛的应用,例如信号处理、通信、图像处理、计算机科学、物理学、生物学等。它最大的功能是能够分析和提取信号的特征,将复......
  • 图的数据结构及基础算法
    图(Graph)这个数据结构在平时开发中遇到的比较少,但我认为它是十分重要的,因为从真实的世界中来看,很多东西都可以抽象为图的表示,比如人际关系,地理位置,天马行空的东西都可以抽象为图,所以它比链表等基础数据结构高级一点点,也比较复杂,属于非线性结构。数学中有一个图论的分支也是与其有......
  • JAVA基础
    打开CMD的方式1.开始+系统+命令指示符2.win+r(输入cmd)打开控制台3.在任意的文件夹下面按住(shift)+鼠标右键点击,在此处打开命令窗口4.资源管理器的地址栏前面加上cmd路径5.管理员方式运行(开始-windows系统-命令提示符-鼠标右键更多-管理员方式运行常用dos命令1.盘符切换:英......