优缺点

  • 二进制编码,格式紧凑,编解码快,占用内存小

  • 可读性非常差,不利于调试

命令

protoc [OPTION] PROTO_FILES

基本用法

  • 输出c++代码

    protoc --cpp_out=. base.proto
    

API

  • 基本类型(uint32string等)提供了set_方法

  • singular(单数) message字段(自定义消息),提供mutalbe_方法设置值,没有set_方法

  • repeated字段

    • _size查询数量
    • 下标访问(获取,修改)
    • add_添加(返回指针来修改数据)

编码风格(https://developers.google.com/protocol-buffers/docs/style)

  • 消息类型

    CamelCase(with an initial capital)

  • 字段

    underscore_separated_names

1
2
3
4
5
6
7
8
9
10
11
message SongServerRequest {
required string song_name = 1;
}

C++:
const string& song_name() { ... }
void set_song_name(const string& x) { ... }

Java:
public String getSongName() { ... }
public Builder setSongName(String v) { ... }
  • 枚举

    Use CamelCase (with an initial capital) for enum type names and CAPITALS_WITH_UNDERSCORES for value names

1
2
3
4
enum Foo {
FIRST_VALUE = 1;
SECOND_VALUE = 2;
}
  • service

    CamelCase (with an initial capital) for both the service name and any RPC method names

1
2
3
service FooService {
rpc GetSomething(FooRequest) returns (FooResponse);
}

编码原理(https://developers.google.com/protocol-buffers/docs/encoding)

消息结构

Varint

采用类似于UTF-8编码方式,来编码整型数,该数为uint64类型,负数采用补码,所以占用8B,对应需要10B(ceil((8 * 8) / 7))

  • 每个字节用7bits来编码数字

  • 单字节的最高位(Most Significant Bit),来表示是否还有后续字节(1表示有,0表示没有)。

  • 多字节数采用小端字节序

1
2
3
1 => 0000 0001
150(1001 0110) => 10010110 00000001
300(0000 0001 0010 1100) => 1010 1100 0000 0010

源码(encode.go):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const maxVarintBytes = 10 // maximum length of a varint

// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
// Not used by the package itself, but helpful to clients
// wishing to use the same encoding.
func EncodeVarint(x uint64) []byte {
var buf [maxVarintBytes]byte
var n int
for n = 0; x > 127; n++ {
buf[n] = 0x80 | uint8(x&0x7F)
x >>= 7
}
buf[n] = uint8(x)
n++
return buf[0:n]
}

具体有key(tag+type)lengthvalue(int32, int64, uint32, uint64, sint32, sint64, bool, enum)使用varint编码。

参考

  1. https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

留言

2016-03-18