演示说明
本例子的功能为grpc客户端向服务端写入位置信息和读取位置信息,演示环境为ubuntu。
准备工作
安装protobuf编译器:
1 2 3
| 1apt install protobuf-compiler
2
3 |
演示实例
新建工程
1 2 3
| 1cargo new use_grpc --lib #记住这个名字use_grpc,因为在编写代码的时候要用
2
3 |
新建proto文件
在use_grpc目录下,创建foobar.proto文件,编写代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| 1syntax = "proto3";
2
3package foobar;
4
5service FooBarService {
6 rpc record_cab_location(CabLocationRequest) returns (CabLocationResponse);
7 rpc get_cabs(GetCabRequest) returns (GetCabResponse);
8}
9
10message CabLocationRequest {
11 string name = 1;
12 Location location = 2;
13}
14
15message CabLocationResponse {
16 bool accepted = 1;
17}
18
19message GetCabRequest {
20 Location location = 1;
21}
22
23message GetCabResponse {
24 repeated Cab cabs = 1;
25}
26
27message Cab {
28 string name = 1;
29 Location location = 2;
30}
31
32message Location {
33 float latitude = 1;
34 float longitude = 2;
35}
36
37 |
创建构建脚本
在use_grpc目录下,创建build.rs文件,编辑如下:
1 2 3 4 5 6 7 8 9 10 11 12
| 1extern crate protoc_rust_grpc;
2
3fn main() {
4 protoc_rust_grpc::Codegen::new()
5 .out_dir("src")
6 .input("foobar.proto")
7 .rust_protobuf(true)
8 .run()
9 .expect("protoc-rust-grpc");
10}
11
12 |
编写Cargo.toml文件
在文件中添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 1[dependencies]
2protobuf = "2"
3grpc = "0.7.1"
4grpc-protobuf = "0.7.1"
5futures = "0.3.*"
6tls-api = "0.3.*"
7
8[build-dependencies]
9protoc-rust-grpc = "0.7.1"
10
11[[bin]]
12name = "client"
13test = false
14
15[[bin]]
16name = "server"
17test = false
18
19 |
编写源码
编写lib.rs
编写src目录下lib.rs,如下:
1 2 3 4
| 1pub mod foobar;
2pub mod foobar_grpc;
3
4 |
编写服务端
在src目录下创建bin目录,在bin目录中创建server.rs,编写如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| 1use std::thread;
2
3use use_grpc::foobar_grpc::*;//use_grpc为当前包的名字,如果名字不一样需要修改
4use use_grpc::foobar::*;//use_grpc为当前包的名字,如果名字不一样需要修改
5
6struct FooBarServer;
7
8impl FooBarService for FooBarServer {
9 fn record_cab_location(&self,
10 _o: grpc::ServerHandlerContext,
11 req: grpc::ServerRequestSingle<CabLocationRequest>,
12 resp: grpc::ServerResponseUnarySink<CabLocationResponse>)
13 -> grpc::Result<()>
14 {
15 let mut r = CabLocationResponse::new();
16
17 println!("Recorded cab {} at {}, {}", req.message.get_name(), req.message.get_location().latitude, req.message.get_location().longitude);
18
19 r.set_accepted(true);
20 resp.finish(r)
21 }
22
23 fn get_cabs(&self,
24 _o: grpc::ServerHandlerContext,
25 _req: grpc::ServerRequestSingle<GetCabRequest>,
26 resp: grpc::ServerResponseUnarySink<GetCabResponse>)
27 -> ::grpc::Result<()>
28 {
29 let mut r = GetCabResponse::new();
30
31 let mut location = Location::new();
32 location.latitude = 40.7128;
33 location.longitude = -74.0060;
34
35 let mut one = Cab::new();
36 one.set_name("Limo".to_owned());
37 one.set_location(location.clone());
38
39 let mut two = Cab::new();
40 two.set_name("Merc".to_owned());
41 two.set_location(location.clone());
42
43 let vec = vec![one, two];
44 let cabs = ::protobuf::RepeatedField::from_vec(vec);
45
46 r.set_cabs(cabs);
47
48 resp.finish(r)
49 }
50}
51
52fn main() {
53 let mut server = grpc::ServerBuilder::new_plain();
54 server.http.set_port(9001);
55 server.add_service(FooBarServiceServer::new_service_def(FooBarServer));
56 // server.http.set_cpu_pool_threads(4);
57 let _server = server.build().expect("Could not start server");
58 loop {
59 thread::park();
60 }
61}
62
63 |
编写客户端
在src/bin目录下创建client.rs,编写如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 1use use_grpc::foobar::*;//use_grpc为当前包的名字,如果名字不一样需要修改
2use use_grpc::foobar_grpc::*;//use_grpc为当前包的名字,如果名字不一样需要修改
3use futures::executor;
4
5use grpc::ClientStubExt;
6
7
8fn main() {
9 let client =
10 FooBarServiceClient::new_plain("127.0.0.1",
11 9001,
12 Default::default())
13 .unwrap();
14
15 let mut req = CabLocationRequest::new();
16 req.set_name("foo".to_string());
17
18 let mut location = Location::new();
19 location.latitude = 40.730610;
20 location.longitude = -73.935242;
21 req.set_location(location);
22
23 let resp = client
24 .record_cab_location(grpc::RequestOptions::new(), req)
25 .join_metadata_result();
26 let resp = executor::block_on(resp);
27 match resp {
28 Err(e) => panic!("{:?}", e),
29 Ok((_, r, _)) => println!("{:?}", r),
30 }
31
32 let mut nearby_req = GetCabRequest::new();
33 let mut location = Location::new();
34 location.latitude = 40.730610;
35 location.longitude = -73.935242;
36 nearby_req.set_location(location);
37
38 let nearby_resp = client
39 .get_cabs(grpc::RequestOptions::new(), nearby_req)
40 .join_metadata_result();
41 let nearby_resp = executor::block_on(nearby_resp);
42 match nearby_resp {
43 Err(e) => panic!("{:?}", e),
44 Ok((_, cabs, _)) => println!("{:?}", cabs),
45 }
46}
47
48 |
编译
编译完成后的目录结构为:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1use_grpc
2 |----- build.rs
3 |----- Cargo.toml
4 |----- foobar.proto
5 |----- src
6 |----- lib.rs
7 |----- foobar_grpc.rs
8 |----- foobar.rs
9 |----- bin
10 |----- client.rs
11 |----- server.rs
12
13 |
其中foobar_grpc.rs和foobar.rs为编译生成的文件。
运行
进入到target/Debug目录下。