2017-01-12 16 views
1

Например, если я определяю фото вроде этого:Как protobuf судит, принадлежит ли значение к необязательному полю или другому объекту?

$cat 30.proto 
message hello 
{ 
    required int32 f1=1; 
    required int32 f2=2; 
    optional int32 f3=3; 
} 

Тогда я бы удвоиться, если Protobuf может обрабатывать такие вещи:

  1. Я объявляю 3 объектов, каждый не f3 поле.

  2. Запись на выходе

  3. Затем в сторону читателя, каким образом читатель знает, что эти 6 значения должны принадлежать к 3 объектам (каждые 2 поля), или принадлежат к 2 объектам (каждые 3 поля)?

В другом слове, как «требуется»/«необязательно» отражено внутри закодированных байтов? Если не отражено в потоке байтов, то как protobuf определяет начало нового смещения? Мы знаем, что протобуф не имеет бит «разделителя».

У меня был простой быстрый тест на это:

$cat 30.cpp 
#include "30.pb.h" 
#include<fstream> 
using namespace std; 
int main() 
{ 
    fstream f("./log30.data",ios::binary|ios::out); 
    hello p1,p2,p3,p4,p5; 
    p1.set_f1(1); 
    p1.set_f2(2); 
    p2.set_f1(3); 
    p2.set_f2(4); 
    p3.set_f1(5); 
    p3.set_f2(6); 
    p1.SerializeToOstream(&f); 
    p2.SerializeToOstream(&f); 
    p3.SerializeToOstream(&f); 

    p4.set_f1(7); 
    p4.set_f2(8); 
    p4.set_f3(9); 
    p5.set_f1(0xa); 
    p5.set_f2(0xb); 
    p5.set_f3(0xc); 
    p4.SerializeToOstream(&f); 
    p5.SerializeToOstream(&f); 
    return 0; 
} 

$g++ 30.cpp 30.pb.cc -lprotobuf && ./a.out && xxd log30.data 
00000000: 0801 1002 0803 1004 0805 1006 0807 1008 ................ 
00000010: 1809 080a 100b 180c      ........ 

Я только догадывался, если поток байт всегда начинается с наименьшим числом тегов, и возрастает, как он сбрасывает поток байтов: когда число меньше тега он считает, что это начало нового объекта. Просто моя скромная догадка.

Нужно ваше объяснение!

ответ

1

(3) Тогда, в стороне читателя, каким образом читатель знает, что эти 6 значения должны принадлежать 3 объектов (каждые 2 поля), или принадлежат к 2 объектам (каждый 3 поля)?

В другом слове, как «требуется»/«необязательно» отражено внутри закодированных байтов? Если не отражено в байтовом потоке, то как protobuf определяет начало нового смещения? Мы знаем, что protobuf не имеют бит «разделителя».

Protobuf - нет. Это зависит от вас, программист, чтобы разделить сообщения, прежде чем вы их кормите до protobuf.

Например, запустить эту программу:

#include "30.pb.h" 
#include <fstream> 
#include <iostream> 
using namespace std; 
int main() 
{ 
    fstream f("./log30.data",ios::binary|ios::out); 
    hello p1,p2,p3,p4,p5; 
    p1.set_f1(1); 
    p1.set_f2(2); 
    p2.set_f1(3); 
    p2.set_f2(4); 
    p3.set_f1(5); 
    p3.set_f2(6); 
    p1.SerializeToOstream(&f); 
    p2.SerializeToOstream(&f); 
    p3.SerializeToOstream(&f); 

    p4.set_f1(7); 
    p4.set_f2(8); 
    p4.set_f3(9); 
    p5.set_f1(0xa); 
    p5.set_f2(0xb); 
    p5.set_f3(0xc); 
    p4.SerializeToOstream(&f); 
    p5.SerializeToOstream(&f); 
    f.close(); 
    f.open("./log30.data", ios::binary|ios::in); 

    hello hin; 
    hin.ParseFromIstream(&f); 

    cout << "f1: " << hin.f1() << ", f2: " << hin.f2() << ", f3: " << hin.f3() << "\n"; 
    return 0; 
} 

Вы должны видеть только значение последнего сериализованного hello объекта, как Protobuf читает поток всего и перезаписывает старые значения с новыми.

1

Сформировать documentation

Как вы знаете, сообщение буфер протокола представляет собой серию из пар ключ-значение. Бинарная версия сообщения просто использует номер поля в качестве ключа - имя и объявленный тип для каждого поля могут быть определены только в конце декодирования, ссылаясь на определение типа сообщения (т. Е. Файл .proto).

Когда сообщение закодировано, ключи и значения объединяются в поток байтов.Когда сообщение декодируется, анализатор должен иметь возможность пропускать поля, которые он не распознает. Таким образом, новые поля могут быть добавлены в сообщение, не разбирая старые программы, которые не знают о них. С этой целью «ключ» для каждой пары в сообщении в виде провода представляет собой два значения - номер поля из вашего .proto-файла, а также тип провода, который предоставляет достаточно информации, чтобы найти длину следующего значения.

...

Если определение proto2 сообщение повторил элементы (без [упакована = TRUE] вариант), кодированное сообщение имеет ноль или более пар ключ-значение с таким же числом тегов.

Так что необязательные элементы не могут быть помещены в выходной поток. В то время как требуемый должен быть включен. Схема должна быть известна как для сериализации, так и для десериализации (в отличие от Avro where schema must be embedded with data), поэтому проверка необходимого/необязательного поля происходит после десериализации, когда парсер проверяет, имеют ли все обязательные поля значения.

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

  • Нет связанных вопросов^_^