Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux protobuf如何判断一个值是属于可选字段还是另一个对象?_Linux_Object_Protocol Buffers_Encode_Delimiter - Fatal编程技术网

Linux protobuf如何判断一个值是属于可选字段还是另一个对象?

Linux protobuf如何判断一个值是属于可选字段还是另一个对象?,linux,object,protocol-buffers,encode,delimiter,Linux,Object,Protocol Buffers,Encode,Delimiter,例如,如果我这样定义照片: $cat 30.proto message hello { required int32 f1=1; required int32 f2=2; optional int32 f3=3; } 如果protobuf能处理这样的事情,我会加倍努力: 我声明了3个对象,每个对象都没有f3字段 写入输出 然后,在阅读器端,阅读器如何知道这6个值应该属于3个对象(每个2个字段),还是属于2个对象(每个3个字段) 换句话说,“require”/“optio

例如,如果我这样定义照片:

$cat 30.proto
message hello
{
    required int32 f1=1;
    required int32 f2=2;
    optional int32 f3=3;
}
如果protobuf能处理这样的事情,我会加倍努力:

  • 我声明了3个对象,每个对象都没有
    f3
    字段

  • 写入输出

  • 然后,在阅读器端,阅读器如何知道这6个值应该属于3个对象(每个2个字段),还是属于2个对象(每个3个字段)

  • 换句话说,“require”/“optional”如何反映在编码字节中?如果没有反映在字节流中,那么protobuf如何确定新偏移量的开始?我们知道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                      ........
    
    $cat 30.cpp
    #包括“30.pb.h”
    #包括
    使用名称空间std;
    int main()
    {
    fstream f(“./log30.data”,ios::binary | ios::out);
    你好,p1,p2,p3,p4,p5;
    p1.设置_f1(1);
    p1.设置f2(2);
    p2.集合f1(3);
    p2.设置f2(4);
    p3.集合f1(5);
    p3.设置f2(6);
    p1.流(&f);
    p2.流(&f);
    p3.流和流(f);
    p4.集合f1(7);
    p4.设置f2(8);
    p4.集合f3(9);
    p5.集合f1(0xa);
    p5.设置f2(0xb);
    p5.设置f3(0xc);
    p4.数据流(&f);
    p5.流和流(f);
    返回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。。。。。。。。
    
    我只是猜测,如果字节流总是以最小的标记号开始,并随着它转储字节流而增加:当满足较小的标记号时,它认为这是新对象的开始。只是我谦虚的猜测

    需要你的解释

    (3) 那么,在读者端,读者如何知道这6个值 应属于3个对象(每个2个字段),或属于2个对象(每个 3个字段)

    换句话说,“require”/“optional”如何反映在内部 编码字节?如果没有反映在字节流中,那么如何 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;
    }
    
    #包括“30.pb.h”
    #包括
    #包括
    使用名称空间std;
    int main()
    {
    fstream f(“./log30.data”,ios::binary | ios::out);
    你好,p1,p2,p3,p4,p5;
    p1.设置_f1(1);
    p1.设置f2(2);
    p2.集合f1(3);
    p2.设置f2(4);
    p3.集合f1(5);
    p3.设置f2(6);
    p1.流(&f);
    p2.流(&f);
    p3.流和流(f);
    p4.集合f1(7);
    p4.设置f2(8);
    p4.集合f3(9);
    p5.集合f1(0xa);
    p5.设置f2(0xb);
    p5.设置f3(0xc);
    p4.数据流(&f);
    p5.流和流(f);
    f、 close();
    f、 打开(“./log30.data”,ios::binary | ios::in);
    欣你好,;
    hin.ParseFromIstream(&f);
    不能

    如您所知,协议缓冲区消息是一系列键-值对。消息的二进制版本仅使用字段的编号作为密钥–每个字段的名称和声明类型只能在解码端通过引用消息类型的定义(即.proto文件)来确定

    当消息被编码时,键和值被连接到字节流中。当消息被解码时,解析器需要能够跳过它无法识别的字段。这样,新字段就可以添加到消息中,而不会中断不知道它们的旧程序。为此,“键”对于wire格式消息中的每一对,实际上是两个值–来自.proto文件的字段号,加上一个wire类型,该类型提供的信息刚好足以找到以下值的长度

    如果proto2消息定义有重复的元素(没有[packed=true]选项),则编码消息具有零个或多个具有相同标记号的键值对

    因此,无法将可选元素放入输出流中。必须包括While required。序列化和反序列化都必须知道架构(与相反),因此,当解析器检查所有必需字段是否都有值时,反序列化后会对必需/可选字段进行验证