012 Rust 网络编程,gRPC 演示示例

释放双眼,带上耳机,听听看~!

演示说明

本例子的功能为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
1cargo build//编译
2
3

编译完成后的目录结构为:


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目录下。

  • 先运行服务端

1
2
3
1./server
2
3
  • 运行客户端

1
2
3
1./client
2
3

给TA打赏
共{{data.count}}人
人已打赏
安全技术

Netty 实现 WebSocket 聊天功能

2022-1-11 12:36:11

气候事件

台风“威马逊”致海南文昌市5000间农房坍塌

2014-7-19 8:22:33

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索