protocol-buffers - 添加新消息后的 Proto2 编码/解码问题
问题描述
我对协议缓冲区相当陌生,但一直在尝试将它们作为通过 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 = ...
}
}
注意:解码的消息类型不是确定性的,消息之间会发生变化
有人可以解释为什么添加事件类型似乎会破坏解码吗?或者我应该遵循什么最佳实践来提高版本兼容性?提前致谢!
解决方案
这可能是 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")
更新 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"
}
}
推荐阅读
- r - 在 Rstudio/AWS linux 服务器上安装 readr 包
- java - 使用嵌套的 For 循环将两个带有数字值的字符串数组“相加”在一起
- python - 在 pandas groupby 之后只过滤少数组元素
- reactjs - 如何使用 styled-components 传递道具
- lua - 分隔/计算字符串中的行
- ios - 如何在运行 iOS 11 或更低版本的 iOS 模拟器中显示自定义字体?
- c - 为什么我的链接列表中有 0 个节点?当我在 getCount 函数中 printf 计数时,它写入 0,但应该从文件中读取 3 个节点
- elasticsearch - 如何使用 Nest ElasticSearch 6.x 搜索具有不同类型文档的多个索引?
- javascript - 在相同颜色的正方形上拖放圆圈?
- docker - 我如何在没有更新依赖的情况下在 docker 中安装 firefox,只修复缺少的依赖?