套接字中的多个不同protobuf消息

4

我是一个有用的助手,可以为您翻译文本。

我在我的c++服务器上使用protobuf。但是在套接字中存在多个不同的protobuf消息时出现了问题。我定义了许多proto消息,例如:

message SdkHGetRet {
  required int32 opcode = 1;
  required bytes value = 2;
}

message SdkHPut {
  required bytes table = 1;
  required bytes hname = 2;
  required bytes key = 3;
  required bytes value = 4;
  optional int32 writesrc = 5 [default = 0];
}

message SdkSet {
  required bytes table = 1;
  required bytes key = 2;
  required bytes value = 3;
  optional int32 writesrc = 4 [default = 0];
}

message SdkSetRet {
  required bool status = 1;
  optional string master = 2;
}

message SdkInvalidOperation {
  required int32 what = 1;
  required bytes why = 2;
}
....

每次通过socket发送消息时,我会添加8个字节。其中4个字节用于表示整个socket的长度,另外4个字节表示操作码。操作码意味着消息类型。
在服务器端,当我接收到消息时,我会先读取前4个字节,以获取消息的长度,然后再读取另外4个字节来获取消息的类型,最后再读取消息的长度字节。然后,我将使用消息类型映射到方法映射表(例如404 => "sdkset",405 => "sdksetret")来解码该消息。
我发现这种方法效果不错,但我想知道是否有更优雅的方法来识别消息而无需使用4字节的消息类型。
我已经阅读了消息历史记录,其中一种方法是将整个消息添加到一个大消息中,就像这样:
message BigMessage
{
enum Type { sdkset = 0, sdksetred = 1}
require Type t = 1,
optional  string key = 2,
...
}

由于我有超过40种类型的消息,我认为这种方式可能会影响性能,而且在我看来,这种方式看起来很丑。

那么你能给我任何好的建议吗?

1个回答

10

Protobuf v2.6.0引入了关键字oneof。例如:

message BigMessage {
  oneof message {
    SdkHGetRet hgetret = 1;
    SdkHPut hput = 2;
    ...
  }
}

oneof 确保只有一个字段被设置,并允许您使用 switch() 来确定哪个字段被设置。

请注意,即使在 Protobuf 2.6.0 之前,最好的解决方案也将是一系列可选字段,可能还包括用于指定哪个字段被设置的枚举:

message BigMessage {
  enum Type { HGETRET = 0, HPUT = 1, ... }
  required Type t = 1;
  optional SdkHGetRet hgetret = 2;
  optional SdkHPut hput = 3;
  ...
}

谢谢您的回复。我的考虑是这种方式是否会影响性能?如果这种方式运行良好,我认为这是一种删除代表消息类型的4个字节的好方法。 - baotiao
@baotiao 我认为这不会影响性能,但如果你担心的话,可以进行基准测试。你可能想考虑重用一个消息对象来解析每个消息(当只有一种类型时,这将更容易)-- 这通常会显著提高性能,因为它减少了分配。 - Kenton Varda
是的,使用一个消息对象来解析每个消息将简化我的工作,我将测试使用protobuf的新方法。但是我发现其他项目也与我一样使用protobuf,比如 https://github.com/mhaberler/machinetalk-protobuf/blob/master/proto/object.proto 你认为我们两个都错误地使用了protobuf吗? - baotiao
1
@baotiao - 是的,我强烈建议使用oneof而不是手动编写消息头。 - Kenton Varda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接