文档章节

protocol buffer 基础

o
 osc_ee3ody6v
发布于 07/06 08:30
字数 1329
阅读 10
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

我们知道接口传输数据的格式有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 = "tom@gmail.com"

    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: "tom@gmail.com"

序列化:
 b'\n\x03tom\x10\x01\x1a\rtom@gmail.com'
 
反序列化:
info id: 1
his age:  tom
his phone number : 400100
his phone type : 2

我帮你问:这有什么用?

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

o
粉丝 0
博文 77
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Go-node

Go-node 是一个用 Go 语言实现的 Erlang/OTP node 已支持的功能: Publish listen port via EPMD Handle incoming connection from other node using Erlang Distribution Protocol Spawn E......

匿名
2013/01/25
1.5K
1
django-c10k-demo

这是一个演示程序,用来实现同时 10000 个并发连接到 Django 。涉及的概念包括:the C10k problem, the WebSocket protocol, the Django web framework, and Python's upcoming asynchronou......

匿名
2013/03/27
1.7K
0
C++ 单元测试框架--cipra

cipra 是一个简单的、兼容 TAP (Test Anything Protocol) 的 C++ 单元测试框架。100% 使用标准的 C++11 编写,只提供一组头文件,可很方便的在你的 C++11 项目中使用。...

匿名
2013/04/17
1K
0
OpenOSPFD

OSPFD(Open Shortest Path First Protocol)路由协议的一个开源能实现,是OpenBGPD的姊妹项目。OpenOSPFD和OPENBGPD都是OPENBSD项目的一部分。OpenBSD项目介绍 OPENBSD...

匿名
2013/04/24
640
0
轻量级Web Server框架--Cyclone

Cyclone 是用Python编写的一款异步非阻塞的轻量级Web Server框架。它实现了Tornado的 API,底层实现是基于Twisted Protocol的。 Cyclone项目的主要意义在于,将Tornado优雅简洁的API,移植到...

匿名
2013/05/24
2.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

创建具有列表理解的字典 - Create a dictionary with list comprehension

问题: I like the Python list comprehension syntax. 我喜欢Python列表理解语法。 Can it be used to create dictionaries too? 它也可以用来创建字典吗? For example, by iterating over......

技术盛宴
今天
15
0
从JS数组中删除重复的值[duplicate] - Remove duplicate values from JS array [duplicate]

问题: This question already has answers here : 这个问题已经在这里有了答案 : Get all unique values in a JavaScript array (remove duplicates) (79 answers) 获取JavaScript数组中的......

法国红酒甜
今天
11
0
如何使用AngularJS在浏览器的控制台中访问$ scope变量?

问题: I would like to access my $scope variable in Chrome's JavaScript console. 我想在Chrome的JavaScript控制台中访问$scope变量。 How do I do that? 我怎么做? I can neither see ......

fyin1314
今天
18
0
ImageMagick - 添加水印

背景 最近制作思维导图想添加自己的水印,网上很多例子都是使用ImageMagick来完成。但是不少代码在本地并不可行。经过一番试验,找到两个方法。 方法一 代码 stackoverflow方法改良: conver...

wffger
今天
11
0
OSChina 周四乱弹 —— 到底是怎样的饕餮盛宴在等待着我!

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 小小编辑推荐 :《你 能 來 保 護 我 的 世 界 嘛》- 歪门 《你 能 來 保 護 我 的 世 界 嘛》- 歪门 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
77
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部