cargo new rust_grpc_server cargo new rust_grpc_client分别在项目根目录创建proto文件夹,并在其中创建一个叫hello.proto的文件
syntax = "proto3"; package hello; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings. message HelloReply { string message = 1; }第三步:添加依赖
[dependencies] tonic = "0.6" tokio = { version = "1", features = ["full"] } prost = "0.9" [build-dependencies] tonic-build = "0.6"在client的项目的Cargo.toml文件中添加以下依赖:
[dependencies] tonic = "0.6" tokio = { version = "1", features = ["full"] } prost = "0.9" rand = "0.8" [build-dependencies] tonic-build = "0.6"第四步:创建build脚本
fn main() { tonic_build::compile_protos("proto/hello.proto") .expect("Failed to compile proto files"); }最终生成的代码类似
use std::time::SystemTime; use tonic::{transport::Server, Request, Response, Status}; pub mod hello { tonic::include_proto!("hello"); } use hello::greeter_server::{Greeter, GreeterServer}; use hello::{HelloReply, HelloRequest}; #[derive(Default)] pub struct MyGreeter {} #[tonic::async_trait] impl Greeter for MyGreeter { async fn say_hello( &self, request: Request<HelloRequest>, ) -> Result<Response<HelloReply>, Status> { let reply = hello::HelloReply { message: format!( "Hello {}!,Current Time is {:?}", request.into_inner().name, SystemTime::now() ), }; Ok(Response::new(reply)) } } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let addr = "[::1]:50051".parse()?; let greeter = MyGreeter::default(); println!("GreeterServer listening on {}", addr); Server::builder() .add_service(GreeterServer::new(greeter)) .serve(addr) .await?; Ok(()) }第六步:编写gRPC客户端
use rand::Rng; pub mod hello { tonic::include_proto!("hello"); } use hello::HelloRequest; #[derive(Default)] pub struct MyGreeter {} // 客户端代码 #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // 堆代码 duidaima.com // 客户端测试 let mut client = hello::greeter_client::GreeterClient::connect("http://[::1]:50051").await?; // 随机选择一个字符串出来 let names = ["张三", "李四", "王五"]; let mut rng = rand::thread_rng(); let random_name = names[rng.gen_range(0..names.len())]; let request = tonic::Request::new(HelloRequest { name: random_name.into(), }); let response = client.say_hello(request).await?; println!("RESPONSE={:?}", response.into_inner().message); Ok(()) }编译和运行
2.在client项目根目录执行cargo run来编译和运行项目,客户端将发送一个请求并打印出服务端的响应内容
参考资料
[1]Protobuf Compiler Installation: https://github.com/protocolbuffers/protobuf