Sockets 套接字中有多个不同的protobuf消息 我用C++服务器使用了原Bufff。但是我有一个问题,在一个套接字中有多个不同的protobuf消息 我定义了许多原型消息,例如 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; } ....

Sockets 套接字中有多个不同的protobuf消息 我用C++服务器使用了原Bufff。但是我有一个问题,在一个套接字中有多个不同的protobuf消息 我定义了许多原型消息,例如 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; } ....,sockets,protocol-buffers,Sockets,Protocol Buffers,因此,每次我通过套接字发送消息时,我都会添加8个字节,4个字节表示总套接字长度,4个字节表示操作码,操作码表示消息类型 所以在服务器端,我接收消息,读取前4个字节,得到消息的长度,然后再读取另外4个字节得到消息的类型,最后读取消息的长度字节。然后我将使用消息类型到方法映射(例如404=>“sdkset”,405=>“sdksetet”)来解码消息 我发现这种方法工作得很好,但我想知道是否有任何优雅的方法可以在没有4字节消息类型的情况下识别消息。 我已经阅读了消息历史记录,一种方法是将整个消息添加

因此,每次我通过套接字发送消息时,我都会添加8个字节,4个字节表示总套接字长度,4个字节表示操作码,操作码表示消息类型

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

我发现这种方法工作得很好,但我想知道是否有任何优雅的方法可以在没有4字节消息类型的情况下识别消息。 我已经阅读了消息历史记录,一种方法是将整个消息添加到一条大消息中,就像这样

message BigMessage
{
enum Type { sdkset = 0, sdksetred = 1}
require Type t = 1,
optional  string key = 2,
...
}
因为我有40多种类型的消息,我认为这种方式可能会影响性能,在我看来,这种方式看起来很难看


因此,您能给我一些好的建议吗?

为此推出的Protobuf v2.6.0。例如:

message BigMessage {
  oneof message {
    SdkHGetRet hgetret = 1;
    SdkHPut hput = 2;
    ...
  }
}
oneof
确保恰好设置了其中一个字段,并允许您在其中一个字段上切换()

请注意,即使在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我认为这不会影响性能,但如果您担心,应该进行基准测试。您可能需要考虑重用一个消息对象来解析每个消息(当只有一种类型时,这将是非常容易的)——这通常会提高性能,因为它减少了分配。是的,使用一个消息对象来解析每个消息将仅仅是我的工作,我将测试使用原BUFF的新方式。但我发现其他一些项目使用protobuf的方式与我相同。比如,你认为我们使用protobuf的方式都不对吗?@baotiao-是的,我强烈建议使用其中一个,而不是手动滚动消息头。