每一个字段都必须用以下之一的修饰符来修饰:
- required:必 须提供字段值,否则对应的消息就会被认为是“未初始化的”。如果libprotobuf是以debug模式编译的,序列化一个未初始 化的消息(message)将会导致一个断言错误。在优化过的编译情况下(译者注:例如release),该检查会被跳过,消息会被写入。然而,解析一个 未初始化的消息仍然会失败(解析函数会返回false)。除此之外,一个required的字段与一个optional的字段就没有区别了。
- optional:字 段值指定与否都可以。如果没有指定一个optional的字段值,它就会使用默认值。对简单类型来说,你可以指定你自己的默认值,就 像我们在上面的例子中对phone number的type字段所做的一样。如果你不指定默认值,就会使用系统默认值:数据类型的默认值为0,string的默认值为空字符串,bool的默 认值为false。对嵌入式消息(message)来说,其默认值总是消息的“默认实例”或“原型”,即:没有任何一个字段是指定了值的。调用访问类来取 一个未显式指定其值的optional(或者required)的字段的值,总是会返回字段的默认值。
- repeated:字 段会重复N次(N可以为0)。重复的值的顺序将被保存在protocol buffer中。你只要将重复的字段视为动态大小的数组就可以了。
每一个protocol buffer类都有读写你所选择的消息类型的函数。它们包括:
l bool SerializeToString(string* output) const;:将消息序列化并储存在指定的string中。注意里面的内容是二进制的,而不是文本;我们只是使用string作为一个很方便的容器。
l bool ParseFromString(const string& data);:从给定的string解析消息。
l bool SerializeToOstream(ostream* output) const;:将消息写入到给定的C++ ostream中。
l bool ParseFromIstream(istream* input);:从给定的C++ istream解析消息。
这些函数只是用于解析和序列化的几个函数罢了。请再次参考Message API reference以查看完整的函数列表。
扩展一个protocol buffer,如果你想让你的新buffer向后兼容(backwards-compatible),并且旧的buffer能够向前兼容(forward-compatible)——你一定希望如此——那么你在新的protocol buffer中就要遵守其他的一些规则了:
l 对已存在的任何字段,你都不能更改其标识(tag)号。
l 你绝对不能添加或删除任何required的字段。
l 你可以添加新的optional或repeated的字段,但是你必须使用新的标识(tag)号(例如,在这个protocol buffer中从未使用过的标识号——甚至于已经被删除过的字段使用过的标识号也不行)。
Protocol Buffers的作用绝不仅仅是简单的数据存取以及序列化,protocol消息类所提供的一个关键特性就是反射。你不需要编写针对一个特殊的消息(message)类型的代码,就可以遍历一个消息的字段,并操纵它们的值,就像XML和JSON一样。“反射”的一个更高级的用法可能就是可以找出两个相同类型的消息之间的区别,或者开发某种“协议消息的正则表达式”,利用正则表达式,你可以对某种消息内容进行匹配。只要你发挥你的想像力,就有可能将Protocol Buffers应用到一个更广泛的、你可能一开始就期望解决的问题范围上。
“反射”是由Message::Reflection interface提供的。
通过它的SerializeToString发放,把内容序列化到string 中,然后把string 通过网络发送。接收端,收到后,用ParseFromString可以获得 Google Protocol Buffer对象。
protoc.exe -proto_path=SRC --cpp_out=DST SRC/addressbook.proto
其中--proto_path指出proto文件所在的目录,--cpp_out则是生成的代码文件要放的目录,最后的一个参数指出proto文件的路径。如上述命令中可以看出,将SRC目录下的addressbook.proto编译后放在DST目录下,应该会生成addressbook.pb.h和addressbook.pb.cc文件(/Files/royenhome/addressbook.rar)。
每个字段中的函数:
// required string number = 1;
inline bool has_number() const;
inline void clear_number();
inline const ::std::string& number() const;
inline void set_number(const ::std::string& value);
inline void set_number(const char* value);
inline ::std::string* mutable_number();
可以看出,对于每个字段会生成一个has函数(has_number)、clear清除函数(clear_number)、set函数(set_number)、get函数(number和mutable_number)。这儿解释下get函数中的两个函数的区别,对于原型为const std::string &number() const的get函数而言,返回的是常量字段,不能对其值进行修改。但是在有一些情况下,对字段进行修改是必要的,所以提供了一个mutable版的get函数,通过获取字段变量的指针,从而达到改变其值的目的。
Base 128 Varints:
在理解Protocol Buffer的编码规则之前,你首先需要了解varints。varints是一种使用一个或多个字节表示整型数据的方法。其中数值本身越小,其所占用的字节数越少。
在varint中,除了最后一个字节之外的每个字节中都包含一个msb(most significant bit)设置(使用最高位),这意味着其后的字节是否和当前字节一起来表示同一个整型数值。而字节中的其余七位将用于存储数据本身。由此我们可以简单的解释一下Base 128,通常而言,整数数值都是由字节表示,其中每个字节为8位,即Base 256。然而在Protocol Buffer的编码中,最高位成为了msb,只有后面的7位存储实际的数据,因此我们称其为Base 128(2的7次方)。
Protocol Buffer中的消息都是由一系列的键值对构成的。每个消息的二进制版本都是使用标签号作为key,而每一个字段的名字和类型均是在解码的过程中根据目标类型(反序列化后的对象类型)进行配对的。
key信息之后是字节数组的长度信息,最后在紧随指定长度的实际数据值信息
在.proto文件中定义消息的字段标号时,可以是不连续的,但是如果将其定义为连续递增的数值,将获得更好的编码和解码性能。
http协议是什么?
Http get 方法 如何实现 (用curl)
http post 方法 如何实现 (用curll)
get 和 post有什么不同。
http 下载文件,, 断点下载
http 上传, 断点上传
文件操作,C文件操作