添加新消息后的 Proto2 编码/解码问题
Posted
技术标签:
【中文标题】添加新消息后的 Proto2 编码/解码问题【英文标题】:Proto2 encode/decode issues after adding new message 【发布时间】:2021-11-17 23:44:19 【问题描述】:我对协议缓冲区还很陌生,但一直在尝试将它们作为通过 MQTT 发送数据的一种方式来学习。到目前为止,我已经很好地创建了 proto 消息并为 python 运行时编译它们,直到我开始注意到我的 protobufs 版本之间的不兼容。
当我向服务器端原型定义添加消息类型(不更改现有消息/字段)而不更新客户端原型定义时,解码发送到服务器的消息会给我带来不确定的结果。
下面是我所说的一个例子:
客户端原型:
message Wrapper
optional uint32 id = 1;
optional string name = 2;
oneof payload
Event event = 3;
Command command = 4;
message Event
uint32 event_id = 1;
oneof event_payload
LoginEvent login_event = 2;
LogoffEvent logoff_event = 3;
服务器原型:
message Wrapper
optional uint32 id = 1;
optional string name = 2;
oneof payload
Event event = 3;
Command command = 4;
message Event
uint32 event_id = 1;
oneof event_payload
LoginEvent login_event = 2;
LogoffEvent logoff_event = 3;
NewUserEvent new_user_event = 4;
我将编码并从客户端发送一条消息:
message Wrapper
id = 12345;
name = John;
event =
login_event = ...
并将在服务器上解码消息并获取:
message Wrapper
id = 12345;
name = John;
event =
logoff_event = ...
注意:解码后的消息类型不确定,消息之间会发生变化
有人可以解释为什么添加事件类型似乎会破坏解码吗?或者我应该遵循什么最佳实践来提高版本兼容性?提前致谢!
【问题讨论】:
【参考方案1】:这可能是 Python 实现的副作用,而不是错误。
您没有包含用于(取消)编组 protobuf 的代码。
在您的示例中,logoff_event
是否包含 LogoffEvent
消息类型?
你说不确定?对于客户端发送的相同消息,您是否在服务器上看到不同的 event_payload
消息类型?
返回的内容:
msg = Wrapper() # Your decoded message
assert msg.event.WhichOneof("event_payload")
# or
assert msg.event.HasField("login_event")
见Python Generated Code: OneOf
更新 210927
我无法重现您观察到的行为;它按我的预期工作。
客户:
import client_pb2
msg = client_pb2.Wrapper()
msg.id=0
msg.name="Test"
msg.event.event_id=1
msg.event.login_event.y="Hello Freddie"
print(msg)
f=open("message","wb")
f.write(msg.SerializeToString())
f.close()
产量:
id: 0
name: "Test"
event
event_id: 1
login_event
y: "Hello Freddie"
服务器:
import server_pb2
msg = server_pb2.Wrapper()
f=open("message","rb")
msg.ParseFromString(f.read())
f.close
assert msg.event.WhichOneof("event_payload")
assert msg.event.HasField("login_event")
print(msg)
产量:
id: 0
name: "Test"
event
event_id: 1
login_event
y: "Hello Freddie"
【讨论】:
是的,logff_event
确实包含 LogoffEvent 消息类型,是的,这正是我所说的非确定性。不过,我可能对此不正确,我可能只是缺少一个映射/模式。此外,为了解组,我使用 FromString 方法,然后使用 json_format.MessageToJson 将 msg 转换为 json,我最终将其加载为 python 字典。
我已经更新了我的答案。它按我的预期工作。以上是关于添加新消息后的 Proto2 编码/解码问题的主要内容,如果未能解决你的问题,请参考以下文章
定义了protobuf-net序列化所需的proto2消息类型?