脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - python使用protobufde的过程解析

python使用protobufde的过程解析

2021-12-23 00:08roy8666 Python

Google开源的一个序列化框架,类似于xml , json。最大的特点是基于 二进制,比传统的xml表示同样的内容要短小很多。亦可定义一些可选字段,用于服务端与客户端通信

概念

protobuf(google protocol buffers)是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库.它和xml和json数据差不多,把数据已某种形式保存起来.protobuf相对与xml和json的不同之处,它是一种二进制的数据格式,具有更高的传输,打包和解包效率

优点:

1:序列化后体积相比json和xml很小,适合网络传输

2:支持跨平台多语言

3:消息格式升级和兼容性还不错

4:序列化反序列化速度很快,快于json的处理速度

缺点:

1、以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 protobuf 的任何内容。

2、功能简单,无法用来表示复杂的概念。

标准数据类型

一个标量消息字段可以含有一个如下的类型——该表格展示了定义于.proto文件中的类型,以及与之对应的、在自动生成的访问类中定义的类型

python使用protobufde的过程解析

基于序号的协议字段映射(类似key-value结构)

新建 test.proto

在消息中承载的数据分别对应于每一个字段都有一个名字和一种类型。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
syntax = "proto3";
 
package  weightestimationupdate;
option   java_package = "com.muyuan.platform.bar.patrol.pro";
// 请求包基类(没有附加数据,通信包不重新定义直接使用基类包)
message baserequestcommon
{
  string      deviceid = 1;    // 设备编号
  string      msgid = 2;    // 消息id,用uuid
  string      timestamp = 3;    // unix时间戳(秒)
  uint32      cmd = 4;    // 指令信息
  bytes       payload = 5// 消息体
}
 
// 上报
message deviceregist
{
  string  version = 1;    //
  string  macaddr = 2;    //
}
 
// 下发
message pushupgradeinfo
{
  string  version = 1;            // 版本号
  string  packagename = 2;          //
  string  packagemd5 = 3;          //
  string  packageurl = 4;          //
}
 
// 上报
message reportweightestimationstatus
{
  string      version = 1;    //
  string      state = 2;      //
}
 
// 指令列表
enum emcmd
{
  cmd_none = 0x0000;       // 指令开始范围
 
  //-----------------服务器端主动下发到设备端信令定义开始------------------
  cmd_s2c_push_upgrade_info = 0x0013;    // 下发(协议包:pushupgradeinfo)
  //-----------------服务器端主动下发到设备端信令定义结束-----------------
 
  //-----------------设备端主动上报到服务端信令定义开始-------------------
  cmd_c2s_report_regist = 0x0060;   // 注册(协议包:weightestimationregist)
  cmd_c2s_report_fault = 0x0061;   // 上报故障(协议包:reportfault)
  cmd_c2s_report_weight_estimation_status = 0x0063;    // 上报状态信息(协议包:weightestimationstatus)
  //-----------------设备端主动上报到服务端信令定义结束-----------------
 
  cmd_end = 0xffff;        // 指令结束范围
}

情况1: 收到通信信息

?
1
2
3
4
5
6
7
8
9
import test_pb2 as weight_pd
base_request_common_obj = weight_pd.baserequestcommon()
base_request_common_obj.parsefromstring(msg)
payload = base_request_common_obj.payload
push_upgrade_info_obj = weight_pd.pushupgradeinfo()
push_upgrade_info_obj.parsefromstring(payload)
update_version = push_upgrade_info_obj.version
update_zip_filename = push_upgrade_info_obj.packagename
# 反向解析即可

情况2:发送通信信息

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import test_pb2 as weight_pd
base_request_common = weight_pd.baserequestcommon()
base_request_common.deviceid = deviceid
base_request_common.msgid = str(uuid.uuid4())
base_request_common.timestamp = str(int(time.time()))
# change
item_list = weight_pd.emcmd.items()
#此为 protobuf 3.0.0 版本的
weight_dict = listtuple_dict(item_list)
base_request_common.cmd = weight_dict.get("cmd_c2s_report_weight_estimation_status")
#此为 protobuf 最新版本 
# base_request_common.cmd = weight_pd.emcmd.cmd_c2s_report_weight_estimation_status
report_weight_estimation_status = weight_pd.reportweightestimationstatus()
report_weight_estimation_status.version = self.version
report_weight_estimation_status.state = state
base_request_common.payload = report_weight_estimation_status.serializetostring()
serializetostring = base_request_common.serializetostring()
#  serializetostring 即为 二进制数据流
def listtuple_dict(item_list):
    weight_cmd_dict = {}
    for k, v in item_list:
        weight_cmd_dict.setdefault(k, v)
    return weight_cmd_dict```

到此这篇关于python使用protobuf的文章就介绍到这了,更多相关python使用protobuf内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/roy8666/article/details/119808376

延伸 · 阅读

精彩推荐