cargo.toml:
[[bin]] # 用来运行 HelloWorld gRPC 服务器的可执行文件
name = "server"
path = "src/server.rs"
[[bin]] # 用来运行 HelloWorld gRPC 客户端的可执行文件
name = "client"
path = "src/client.rs"
[dependencies]
# GRPC服务所依赖的包
tonic = "0.7"
# 序列化/反序列化
prost = "0.10"
# 异步框架
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
[build-dependencies]
tonic-build = "0.7"
新建bulid.rs(Cargo.toml同目录):
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::compile_protos("proto/records.proto")?;
Ok(())
}
然后建立proto文件夹(Cargo.toml同目录),然后建立records.proto:
syntax = "proto3";
package records;
service Recorder {
rpc SendMessage(RecordRequest) returns (RecordResponse);
}
message RecordRequest {
string user_name = 1;
string user_age = 2;
}
message RecordResponse {
bool successful = 1;
string message = 2;
}
src下建立client.rs:
use records::recorder_client::RecorderClient;
use records::RecordRequest;
use tonic::{Request};
pub mod records {
tonic::include_proto!("records");
}
#[tokio::main]
async fn main()-> Result<(), Box<dyn std::error::Error>>{
let mut client = RecorderClient::connect("http://[::1]:50050").await?;
let request = Request::new(
RecordRequest{
user_name:"原子".to_string(),
user_age: "45".to_string(),
}
);
let response = client.send_message(request).await?;
println!("{:#?}", response);
println!("===============================");
println!("Meta: {:#?}", response.metadata());
println!("===============================");
println!("Message: {:#?}", response.get_ref());
Ok(())
}
在src下建立server.rs:
use records::recorder_server::{Recorder,RecorderServer};
use records::{RecordRequest,RecordResponse};
use tonic::transport::Server;
use tonic::{Request,Response,Status};
use::std::net::SocketAddr;
pub mod records{
tonic::include_proto!("records");
}
#[derive(Debug,Default)]
pub struct RecorderService{}
#[tonic::async_trait]
impl Recorder for RecorderService{
async fn send_message(
&self,
request: Request<RecordRequest>
) -> Result<Response<RecordResponse>,Status> {
println!("request: {:#?}", request);
let req = request.into_inner();
let response = RecordResponse{
successful: true,
message: format!("User {} is {} old!",req.user_name,req.user_age).into()
};
Ok(Response::new(response))
}
}
#[tokio::main]
async fn main()-> Result<(), Box<dyn std::error::Error>>{
let addr:SocketAddr = "[::1]:50050".parse()?;
let recorder = RecorderService::default();
println!("Recorder listening on {}!", addr);
Server::builder()
.add_service(RecorderServer::new(recorder))
.serve(addr)
.await?;
Ok(())
}
运行server.rs:cargo run --bin server
运行client.rs: cargo run --bin client