【问题标题】:multiple different protobuf messages in a socket套接字中的多个不同的 protobuf 消息
【发布时间】:2015-11-17 08:32:31
【问题描述】:

我在我的 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 len,4个为opcode,opcode表示消息类型。

所以在服务器端,我接收到消息,我读取了前 4 个字节,得到了消息的长度,然后我将读取另外 4 个字节来获取消息的类型,最后我读取了消息的长度字节。然后我将使用消息类型到方法映射(例如404 =>“sdkset”,405 =>“sdksetret”)来解码消息。

我发现这种方式效果很好,但我想知道是否有任何优雅的方式来识别没有 4 字节消息类型的消息。 我已经阅读了消息历史,一种方法是将整个消息添加到一个大消息中,就像这样

message BigMessage
{
enum Type { sdkset = 0, sdksetred = 1}
require Type t = 1,
optional  string key = 2,
...
}

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

那你能给我什么好的建议吗..

【问题讨论】:

    标签: sockets protocol-buffers


    【解决方案1】:

    Protobuf v2.6.0 为此引入了the oneof keyword。示例:

    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 我认为这不会影响性能,但如果你担心你应该进行基准测试。您可能需要考虑重用一个消息对象来解析每条消息(当只有一种类型时这会容易得多)——这通常会大大提高性能,因为它减少了分配。
    • 是的,使用一个消息对象来解析每条消息只是我的工作,我将测试使用 protobuf 的新方法。但我发现其他一些项目和我一样使用 protobuf。比如github.com/mhaberler/machinetalk-protobuf/blob/master/proto/…你认为我们都以错误的方式使用protobuf吗?
    • @baotiao - 是的,我强烈推荐使用oneof,而不是手动滚动消息头。
    猜你喜欢
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多