2015-08-24 2 views
1

Я использую protobuf с моим сервером C++. Но у меня есть проблема с несколькими различными сообщениями Protobuf в сокете я определяю много прото сообщений, такие какнесколько разных сообщений 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; 
} 
.... 

Таким образом, каждый раз, когда я отправить сообщение на сокете, я добавлю 8 байт, 4 на общую розетку len, 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 типов сообщений, я думаю, что этот способ может повлиять на производительность, так и в мое мнение, так выглядит некрасиво.

Так что вы можете дать мне хорошее предложение ..

ответ

3

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; 
    ... 
} 
+0

Спасибо вам ответить. Мое соображение здесь заключается в том, может ли этот способ повлиять на производительность? И если этот способ работает хорошо, я думаю, что это хороший способ удалить 4 байта, которые обозначают тип сообщения. – baotiao

+0

@baotiao Я не думаю, что это повредит производительности, но если вы беспокоитесь, вы должны проверить. Возможно, вам захочется рассмотреть вопрос о повторном использовании одного объекта сообщения для синтаксического анализа каждого сообщения (что будет намного проще при наличии только одного типа) - это обычно значительно повышает производительность, поскольку уменьшает выделение. –

+0

Да, используя один объект сообщения для синтаксического анализа каждого сообщения будет просто моей работой, я буду тестировать новый способ использования protobuf. Но я считаю, что некоторые другие проекты используют protobuf так же, как и я. например https://github.com/mhaberler/machinetalk-protobuf/blob/master/proto/object.proto. Считаете ли вы, что мы оба использовали протобуф неправильно? – baotiao

Смежные вопросы