套接字中的多个不同的 protobuf 消息
multiple different protobuf messages in a socket
我在我的 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 个字节来获取消息的类型,最后我读取了消息的长度字节。然后我会用message type to method map(比如404 => "sdkset", 405 => "sdksetret")来解码message.
我发现这种方式效果很好,但我想知道是否有任何优雅的方式来识别没有 4 字节消息类型的消息。
我看过留言历史,一种方法是把整个留言加到一个大留言里,像这样
message BigMessage
{
enum Type { sdkset = 0, sdksetred = 1}
require Type t = 1,
optional string key = 2,
...
}
由于我有40多种消息类型,我认为这种方式可能会影响性能,而且在我看来,这种方式很难看。
那你有什么好的建议吗..
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;
...
}
我在我的 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 个字节来获取消息的类型,最后我读取了消息的长度字节。然后我会用message type to method map(比如404 => "sdkset", 405 => "sdksetret")来解码message.
我发现这种方式效果很好,但我想知道是否有任何优雅的方式来识别没有 4 字节消息类型的消息。 我看过留言历史,一种方法是把整个留言加到一个大留言里,像这样
message BigMessage
{
enum Type { sdkset = 0, sdksetred = 1}
require Type t = 1,
optional string key = 2,
...
}
由于我有40多种消息类型,我认为这种方式可能会影响性能,而且在我看来,这种方式很难看。
那你有什么好的建议吗..
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;
...
}