本例子的功能為grpc客戶端向服務端寫入位置資訊和讀取位置資訊,演示環境為ubuntu。
安裝protobuf編譯器:
apt install protobuf-compiler
新建工程
cargo new use_grpc --lib #記住這個名字use_grpc,因為在編寫程式碼的時候要用
新建proto檔案
在use_grpc目錄下,建立foobar.proto檔案,編寫程式碼如下:
syntax = "proto3";
package foobar;
service FooBarService {
rpc record_cab_location(CabLocationRequest) returns (CabLocationResponse);
rpc get_cabs(GetCabRequest) returns (GetCabResponse);
}
message CabLocationRequest {
string name = 1;
Location location = 2;
}
message CabLocationResponse {
bool accepted = 1;
}
message GetCabRequest {
Location location = 1;
}
message GetCabResponse {
repeated Cab cabs = 1;
}
message Cab {
string name = 1;
Location location = 2;
}
message Location {
float latitude = 1;
float longitude = 2;
}
建立構建指令碼
在use_grpc目錄下,建立build.rs檔案,編輯如下:
extern crate protoc_rust_grpc;
fn main() {
protoc_rust_grpc::Codegen::new()
.out_dir("src")
.input("foobar.proto")
.rust_protobuf(true)
.run()
.expect("protoc-rust-grpc");
}
編寫Cargo.toml檔案
在檔案中新增如下內容:
[dependencies]
protobuf = "2"
grpc = "0.7.1"
grpc-protobuf = "0.7.1"
futures = "0.3.*"
tls-api = "0.3.*"
[build-dependencies]
protoc-rust-grpc = "0.7.1"
[[bin]]
name = "client"
test = false
[[bin]]
name = "server"
test = false
編寫原始碼
編寫lib.rs
編寫src目錄下lib.rs,如下:
pub mod foobar;
pub mod foobar_grpc;
編寫服務端
在src目錄下建立bin目錄,在bin目錄中建立server.rs,編寫如下:
use std::thread;
use use_grpc::foobar_grpc::*;//use_grpc為當前包的名字,如果名字不一樣需要修改
use use_grpc::foobar::*;//use_grpc為當前包的名字,如果名字不一樣需要修改
struct FooBarServer;
impl FooBarService for FooBarServer {
fn record_cab_location(&self,
_o: grpc::ServerHandlerContext,
req: grpc::ServerRequestSingle<CabLocationRequest>,
resp: grpc::ServerResponseUnarySink<CabLocationResponse>)
-> grpc::Result<()>
{
let mut r = CabLocationResponse::new();
println!("Recorded cab {} at {}, {}", req.message.get_name(), req.message.get_location().latitude, req.message.get_location().longitude);
r.set_accepted(true);
resp.finish(r)
}
fn get_cabs(&self,
_o: grpc::ServerHandlerContext,
_req: grpc::ServerRequestSingle<GetCabRequest>,
resp: grpc::ServerResponseUnarySink<GetCabResponse>)
-> ::grpc::Result<()>
{
let mut r = GetCabResponse::new();
let mut location = Location::new();
location.latitude = 40.7128;
location.longitude = -74.0060;
let mut one = Cab::new();
one.set_name("Limo".to_owned());
one.set_location(location.clone());
let mut two = Cab::new();
two.set_name("Merc".to_owned());
two.set_location(location.clone());
let vec = vec![one, two];
let cabs = ::protobuf::RepeatedField::from_vec(vec);
r.set_cabs(cabs);
resp.finish(r)
}
}
fn main() {
let mut server = grpc::ServerBuilder::new_plain();
server.http.set_port(9001);
server.add_service(FooBarServiceServer::new_service_def(FooBarServer));
// server.http.set_cpu_pool_threads(4);
let _server = server.build().expect("Could not start server");
loop {
thread::park();
}
}
編寫客戶端
在src/bin目錄下建立client.rs,編寫如下:
use use_grpc::foobar::*;//use_grpc為當前包的名字,如果名字不一樣需要修改
use use_grpc::foobar_grpc::*;//use_grpc為當前包的名字,如果名字不一樣需要修改
use futures::executor;
use grpc::ClientStubExt;
fn main() {
let client =
FooBarServiceClient::new_plain("127.0.0.1",
9001,
Default::default())
.unwrap();
let mut req = CabLocationRequest::new();
req.set_name("foo".to_string());
let mut location = Location::new();
location.latitude = 40.730610;
location.longitude = -73.935242;
req.set_location(location);
let resp = client
.record_cab_location(grpc::RequestOptions::new(), req)
.join_metadata_result();
let resp = executor::block_on(resp);
match resp {
Err(e) => panic!("{:?}", e),
Ok((_, r, _)) => println!("{:?}", r),
}
let mut nearby_req = GetCabRequest::new();
let mut location = Location::new();
location.latitude = 40.730610;
location.longitude = -73.935242;
nearby_req.set_location(location);
let nearby_resp = client
.get_cabs(grpc::RequestOptions::new(), nearby_req)
.join_metadata_result();
let nearby_resp = executor::block_on(nearby_resp);
match nearby_resp {
Err(e) => panic!("{:?}", e),
Ok((_, cabs, _)) => println!("{:?}", cabs),
}
}
編譯
cargo build//編譯
編譯完成後的目錄結構為:
use_grpc
|----- build.rs
|----- Cargo.toml
|----- foobar.proto
|----- src
|----- lib.rs
|----- foobar_grpc.rs
|----- foobar.rs
|----- bin
|----- client.rs
|----- server.rs
其中foobar_grpc.rs和foobar.rs為編譯生成的檔案。
執行
進入到target/Debug目錄下。
- 先執行服務端
./server
- 執行客戶端
./client
本作品採用《CC 協議》,轉載必須註明作者和本文連結