反序列化 Google Protobuf 二进制文件

Deserialize Google Protobuf binary file

Google Protobuf 比以往任何时候都更让我困惑,我正试图了解它是如何工作的。

  1. 如果我理解正确,请帮助我理解。 .proto文件定义了消息的定义,protoc是一个编译器。数据编译成二进制文件 (.pb) 。正确的?如果没有,请你帮我理解。我无法处理 Google Protobuf 文档。这很令人困惑。并且在 Stack Overflow 或其他博客上没有任何运气。

  2. 重要,我不能修改定义逻辑的 C++ 代码。话虽如此,我想反序列化 filename.pb(二进制文件)并通过 Python 解析结果。这可能吗?

提前感谢您的帮助!!

是的,您可以使用protoc生成的python代码来反序列化protobuf消息。 protoc 编译器将以您的目标语言输出代码(在您的情况下 pythonC++)。

以下是一些可以提供帮助的资源:

  1. 读取和写入 python 中的文件: https://docs.python.org/2/tutorial/inputoutput.html
  2. Python协议缓冲区消息教程: https://developers.google.com/protocol-buffers/docs/pythontutorial

我不确定我是否在回答你的问题,但我会给你举个例子。一旦你有了 Protocol_pb2.py,你就可以很容易地使用 protobuf python API(可能还有 struct)解析消息。我不是 protobuf 的专家,但我至少解析过 Mumble 消息。现在,我不知道您究竟是如何使用 protobuf 的以及用途是什么,但是这个示例展示了如何解析 mumble 消息(使用 protobuf),并希望能给您一些见解。所以:

导入 protoc 创建的 protobuf 文件(您按照我回答您上一个问题的方式创建它)和结构:

import struct
import Mumble_pb2 as mumble_protobuf

mumble_protobuf 模块将包含转换为 Python 格式的 .proto 文件中定义的不同消息。您可以将不同的消息类型保存到例如字典:

PACKET_TYPES = {
    0: mumble_protobuf.Version,
    1: mumble_protobuf.UDPTunnel,
    2: mumble_protobuf.Authenticate,
...

我在这里略过,但是一旦您收到数据包的二进制数据,您就可以对其进行解析。我想每个应用程序做的事情都不同,但例如 mumble 发送 protobuf 消息,前缀为 2 个字节,包括消息类型,4 个字节告诉数据包长度。这可能在您的应用程序中以不同的方式完成。无论如何,您必须以某种方式知道您将解析哪种消息(假设您的协议有多种消息类型)。但举个例子:

# The header format corresponds to the mumble packet that send the prefix + protobuf-msg
HEADER_FORMAT = ">HI" # Big endian, unsigned short + unsigned int
packet_type, packet_length = struct.unpack_from(HEADER_FORMAT, buffer)

如果缓冲区中有多条消息,则需要根据数据包长度从缓冲区中提取数据包数据。当您知道消息类型时,您可以解析它。这部分只是从pb2文件中获取对应于消息类型的class,并根据它解析消息。

MessageClass = PACKET_TYPES[packet_type]
message = MessageClass()
message.ParseFromString(packet_data)

现在 message 最终将包含已解析的 protobuf 消息,您可以像构建消息一样使用它:您可以引用字段等:message.UserName 或其他内容。