1.grpc 安装编译
安装教程参考BUILDING.md,cmake版本,按照BUILDING.md要求,务必选择cmake大于3.13的版本,否则后期使用缺少关键功能。
大致步骤为:
git clone https://github.com/grpc/grpc.git
git submodule update --init
apt-get install build-essential autoconf libtool pkg-config
apt-get install clang libc++-dev
$ mkdir -p cmake/build
$ cd cmake/build
cmake -DgRPC_INSTALL=ON \
-DgRPC_BUILD_TESTS=OFF \
-DBUILD_SHARED_LIBS=true \
../../
make
make install
2.根据protoc描述文件生成头文件
具体应用可参照
https://www.cnblogs.com/embedded-linux/p/11787696.html
通过下述指定可生成支持GRPC对应服务的头文件
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
protoc --cpp_out=. helloworld.proto
3.proto文件语法(入门版)
3.1.数据类型映射表(只列出了C++)
Type | C++ Type | 描述 |
---|---|---|
double | double | |
float | float | |
int32 | int32 | 使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代 |
uint32 | uint32 | 使用变长编码 |
uint64 | uint64 | 使用变长编码 |
sint32 | int32 | 使用变长编码,这些编码在负值时比int32高效的多 |
sint64 | int64 | 使用变长编码,有符号的整型值。编码时比通常的int64高效。 |
fixed32 | uint32 | 总是4个字节,如果数值总是比总是比228大的话,这个类型会比uint32高效。 |
fixed64 | uint64 | 8个字节,如果数值总是比总是比256大的话,这个类型会比uint64高效 |
sfixed32 | int32 | 4个字节 |
sfixed64 | int64 | 8个字节 |
bool | bool | |
string | string | 字符串必须是UTF-8编码或者7-bit ASCII编码的文本 |
bytes | string | 可能包含任意顺序的字节数据 |
3.2常用语法
ProtoBuf
ProtoBuf 有两个语言版本:v2 与 v3,截止目前在使用 v3 的时候,需要在 *.proto 文件首行中明文标识 syntax:syntax=“proto3”,缺省syntax则默认使用V2
文件第一行一般为:
syntax = "proto3";限定该文件使用的是proto3的语法,
Message
message用来定义一个数据结构,以嵌套使用
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}
字段标示符
v3 去除了 optional、required,不是必须,尽量不要使用required
- required:必须赋值,不能为空
- optional 字段可以赋值,可以不赋值,不赋值会被赋默认值
- repeated 该字段可以重复任意次数(包括零次),使用类似数组
map数据类型
message Employee
{
int64 id = 1;
string name = 2;
map<string, Skill> skills = 3;
}
分配标签
消息中的每一个字段都被定义了一个独一无二的数字标签,这个标签是用来在二进制的消息格式中区分字段的,一旦你的消息开始被使用,这些标签就不应该在被修改了,1 到 15 标签在编码的时候仅占用1 byte ,16 - 2047 占用 2 byte ,能定义的最小的标签是1, 最大是 2的29次方 -1 , 另外 19000 到 19999 也不能用。他们是protobuf 的编译预留标签,另外你也不能使用被 reserved的标签
Reserved
标记为reserved来保证他们不会再次被使用。如果以后的人试用的话protobuf编译器会提示出错,在需要预留字段时可以使用
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
package
每个 *.proto 文件可以指定 package 作为生成语言的 namespace,示例:
package helloworld;
import
import像引入头文件一样引入proto文件,Makefile中,可通过vpath指定proto搜索路径
注释风格
风格和C++差不多 使用双斜杠(//) 语法格式。
Any类型
protobuf中的Any类型与C++中的泛型概念类似,可以定义为任意的类型。在序列化的时候可以通过PackFrom()方法将任意的数据类型打包为Any类型,反序列化的时候通过UnpackTo()把Any类型还原为原始类型。
// 要使用Any类型必须导入该proto文件
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
// Storing an arbitrary message type in Any.
NetworkErrorDetails details = ...;
ErrorStatus status;
status.add_details()->PackFrom(details);
// Reading an arbitrary message from Any.
ErrorStatus status = ...;
for (const Any& detail : status.details()) {
if (detail.Is<NetworkErrorDetails>()) {
NetworkErrorDetails network_error;
detail.UnpackTo(&network_error);
... processing network_error ...
}
}
定义RPC服务(service)
如果想要将消息类型用在远程方法调用(RPC)系统中,可以在.proto文件中定义一个RPC服务接口。
示例
syntax = "proto3";
option java_package = "ex.grpc";
option objc_class_prefix = "HSW";
package hellostreamingworld;
// The greeting service definition.
service MultiGreeter {
// Sends multiple greetings
rpc sayHello (HelloRequest) returns (stream HelloReply) {}
}
//在MultiGreeter服务中,定义一个sayHello接口,参数为HelloRequest,返回值为HelloReply
// The request message containing the user's name and how many greetings
// they want.
message HelloRequest {
string name = 1;
string num_greetings = 2;
}
// A response message containing a greeting
message HelloReply {
string message = 1;
}
如果需要定义无返回值或无参数的接口。
可将返回值或参数置空
message NReply
{
}
Stream
修饰参数,可源源不断的推送数据,适合传输大数据
//声明grpc服务
service Greeter {
/*
以下 分别是 服务端 推送流, 客户端 推送流 ,双向流。
*/
rpc GetStream (StreamReqData) returns (stream StreamResData){}
rpc PutStream (stream StreamReqData) returns (StreamResData){}
rpc AllStream (stream StreamReqData) returns (stream StreamResData){}
}
很适合 传输一些大数据,或者 服务端 和 客户端 长时间 数据交互,比如 客户端 可以向 服务端 订阅 一个数据,服务端 就 可以利用 stream ,源源不断地 推送数据。
客户端推送 服务端 rpc GetStream (StreamReqData) returns (stream StreamResData){}
服务端推送 客户端 rpc PutStream (stream StreamReqData) returns (StreamResData){}
客户端与 服务端 互相 推送 rpc AllStream (stream StreamReqData) returns (stream StreamResData){}
具体使用可参考工程中的示例