Как объяснить формат встроенного двоичного сообщения в буфере протокола? - PullRequest
1 голос
/ 30 мая 2019

Я пытаюсь понять метод кодирования буфера протокола, при переводе сообщения в двоичный (или шестнадцатеричный) формат я не могу понять, как кодируется встроенное сообщение.

Полагаю, возможно, это связано с адресом памяти, но я не могу найти точное отношение.

Вот что я сделал.

Шаг 1: я определил два сообщения в файле test.proto,

syntax = "proto3";
package proto_test;

message Education {
    string college = 1;
}

message Person {
    int32 age = 1;
    string name = 2;
    Education edu = 3;
}

Шаг 2: А потом я сгенерировал некоторый код go,

protoc --go_out=. test.proto

Шаг 3: Затем я проверяю закодированный формат сообщения,

p := proto_test.Person{
    Age:  666,
    Name: "Tom",
    Edu: &proto_test.Education{
        College: "SOMEWHERE",
    },
}
var b []byte
out, err := p.XXX_Marshal(b, true)
if err != nil {
    log.Fatalln("fail to marshal with error: ", err)
}
fmt.Printf("hexadecimal format:% x \n", out)
fmt.Printf("binary format:% b \n", out)

какие выходы,

hexadecimal format:08 9a 05 12 03 54 6f 6d 1a fd 96 d1 08 0a 09 53 4f 4d 45 57 48 45 52 45 
binary format:[ 1000  10011010  101  10010  11  1010100  1101111  1101101  11010  11111101  10010110  11010001  1000  1010  1001  1010011  1001111  1001101  1000101  1010111  1001000  1000101  1010010  1000101]

что я понимаю,

08                         - int32 wire type with tag number 1
9a 05                      - Varints for 666
12                         - string wire type with tag number 2
03                         - length delimited which is 3 byte
54 6f 6d                   - ascii for "TOM"
1a                         - embedded message wire type with tag number 3
fd 96 d1 08                - ? (here is what I don't understand)
0a                         - string wire type with tag number 1
09                         - length delimited which is 9 byte
53 4f 4d 45 57 48 45 52 45 - ascii for "SOMEWHERE"

Что означает fd 96 d1 08? Кажется, что d1 08 всегда будет там, но fd 96 иногда меняется, не знаю почему. Спасибо за ответ:)


Добавить

Я отладил процесс маршала и сообщил об ошибке здесь .

1 Ответ

1 голос
/ 31 мая 2019

В этом месте я ожидаю количество байтов во встроенном сообщении.

Я повторил ваш эксперимент на Python.

msg = Person()
msg.age = 666
msg.name = "Tom"
msg.edu.college = "SOMEWHERE"

Я получил другой результат,один я бы ожидал.Вариант с указанием размера внедренного сообщения.

0x08
0x9A, 0x05
0x12
0x03
0x54 0x6F 0x6D
0x1A 
0x0B                        <- Equals to 11 decimal.
0x0A
0x09
0x53 0x4F 0x4D 0x45 0x57 0x48 0x45 0x52 0x45

Далее я десериализовал ваши байты:

msg2 = Person()
str = bytearray(b'\x08\x9a\x05\x12\x03\x54\x6f\x6d\x1a\xfd\x96\xd1\x08\x0a\x09\x53\x4f\x4d\x45\x57\x48\x45\x52\x45')
msg2.ParseFromString(str)
print(msg2)

Результат этого идеально:

age: 666
name: "Tom"
edu {
  college: "SOMEWHERE"
}

Я пришел к выводу, что в Protobuf есть несколько разных способов кодирования.Я не знаю, что делается в этом случае, но я знаю пример отрицательного 32-разрядного варианта.Положительная переменная кодируется в пять байтов, отрицательное значение преобразуется в 64-разрядное значение и кодируется в десять байтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...