学习笔记

protocol buffer
要创建你的地址薄应用程序,你需要从编写一个.proto文件开始。.proto文件的定义是比较简单的:为每一个你需要序列化的数据结构添加一个消息(message),然后为消息(message)中的每一个字段(field)指定一个名字和一个类型。
各位亲 有时间可以去看看我的  “金骏家居淘宝店” http://jinjun1688.taobao.com/shop/view_shop.htm?tracelog=twddp 买时说明在我的博客看到有优惠哦 还有意外礼品赠送  真正的程序员淘宝店
防止不同项目之间的命名冲突
.proto文件以一个package声明开始。这个声明是为了防止不同项目之间的命名冲突。对应到C++中去,你用这个.proto文件生成的类将被放置在一个与package名相同的命名空间中。

消息(message)定义
一个消息就是某些类型的字段的集合。许多标准的、简单的数据类型都可以用作字段类型,包括boolint32floatdouble,以及string。你也可以使用其他的消息(message)类型来作为你的字段类型——在上面的例子中,消息Person就是一个被用作字段类型的例子。

在每一项后面的、类似于“= 1”,“= 2”的标志指出了该字段在二进制编码中使用的唯一“标识(tag)”。标识号1~15编码所需的字节数比更大的标识号使用的字节数要少1个,所以,如果你想寻求优化,可以为经常使用或者重复的项采用1~15的标识(tag),其他经常使用的optional项采用≥16的标识(tag)。在重复的字段中,每一项都要求重编码标识号(tag number),所以重复的字段特别适用于这种优化情况。

每一个字段都必须用以下之一的修饰符来修饰:

  • 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中。你只要将重复的字段视为动态大小的数组就可以了。
Required是永久性的: 在把一个字段标识为required的时候,你应该特别小心。如果在某些情况下你不想写入或者发送一个 required的字 段,那么将该字段更改为optional可能会遇到问题——旧版本的读者(译者注:即读取、解析消息的一方)会认为不含该字段的消息(message)是 不完整的,从而有可能会拒绝解析。在这种情况下,你应该考虑编写特别针对于应用程序的、自定义的消息校验函数。Google的一些工程师得出了一个结论: 使用required弊多于利;他们更愿意使用optional和repeated而不是required。当然,这个观点并不具有普遍性。

编译命令行语句: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

每一个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  你可以添加新的optionalrepeated的字段,但是你必须使用新的标识(tag)号(例如,在这个protocol buffer中从未使用过的标识号——甚至于已经被删除过的字段使用过的标识号也不行)。


Protocol Buffers的作用绝不仅仅是简单的数据存取以及序列化,protocol消息类所提供的一个关键特性就是反射。你不需要编写针对一个特殊的消息(message)类型的代码,就可以遍历一个消息的字段,并操纵它们的值,就像XMLJSON一样。“反射”的一个更高级的用法可能就是可以找出两个相同类型的消息之间的区别,或者开发某种“协议消息的正则表达式”,利用正则表达式,你可以对某种消息内容进行匹配。只要你发挥你的想像力,就有可能将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文件操作 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值