我正在开发一种系统控制软件,用于处理硬件设备的控制和状态信息。为简单起见,我使用一个中等复杂的协议缓冲区结构来在线程之间进行通信。我还在网络接口上使用相同的结构,以便外部客户端可以控制和监视系统的所有部分。
该软件可能使用低比特率数据链路运行,因此我正在寻找减少网络负载的方法。因此我的问题是:
如果没有为每个I / O操作解析整个protobuf结构,有没有办法过滤(修剪)protobuf以在运行时删除某些消息?
例如,如果我有.proto
:
message Status {
optional BusyMsg busy = 10;
optional FaultMsg system_fault = 11;
optional VoltageMsg rail_volts = 3000;
optional InternalStatus internal = 4000;
}
message InternalStatus {
optional PressureMsg head_pressure = 1;
optional TempMgs cabinet_temp = 2;
}
是否有一种简单的方法可以删除(或禁止传输)rail_volts
或internal
,可能是通过测试大型ID号(在这种情况下为3000和4000)?或者是否可以很好地使用可以提供帮助的扩展和属性?
我知道我可以在I / O边界调用我不想序列化的所有字段的Clear()。但我宁愿在.proto
中标记它们,而不是依赖网络接口上的C ++代码来保持更新。 (到目前为止,internal
子部分是我最好的想法。我可以剪掉一切。)
我不是在寻找一种通过结构研究的解决方案。我想知道我是否缺少API的优雅功能。
答案 0 :(得分:0)
您可以定义缩小的状态消息,将完整的消息打印到字符串,然后将其解析为缩减消息。这意味着您只需要更改proto文件而不必担心C ++ API。 (复制在这里不是很漂亮。我还不知道如何分享这些原型。)
// foo.proto
syntax = "proto2";
message Status1 {
optional int64 f1 = 1;
optional int64 f2 = 2;
optional int64 f3 = 3;
}
message Status2 {
optional int64 f1 = 1;
optional int64 f2 = 2;
}
// foo.cc
#include <iostream>
#include "experimental/seanmcl/proto/foo.pb.h"
int main(int argc, char* argv[]){
string str;
{
Status1 s1;
s1.set_f1(5);
s1.set_f2(6);
s1.set_f3(7);
s1.SerializeToString(&str);
}
{
Status2 s2;
s2.ParseFromString(str);
assert(s2.f1() == 5);
assert(s2.f2() == 6);
}
return 0;
}
关于复制(虽然不是简单的消息),这有点好:
message Status {
optional StatusRequired status_required = 1;
optional int64 f3 = 3;
}
message StatusRequired {
optional int64 f1 = 1;
optional int64 f2 = 2;
}
{
Status s3;
StatusRequired* s4 = s3.mutable_status_required();
s4->set_f1(5);
s4->set_f2(6);
s3.set_f3(7);
s3.SerializeToString(&str);
}
{
Status s3;
s3.ParseFromString(str);
StatusRequired* s4 (s3.mutable_status_required());
cout << (s4->f1() == 5) << endl;;
cout << (s4->f2() == 6) << endl;;
}
我现在认识到的是你的解决方案,字段的相对重要性被翻转了!