rust grpc stream demo

1. 创建项目

cargo new --lib grpc-stream-demo

2. 配置proto

进入项目grpc-stream-demo

2.1 配置Cargo.toml, 内容如下:

[package]
name = "grpc-stream-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
tonic = "0.12.3"
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "full"] }
prost = "0.13.3"
tokio-stream = "0.1"
futures = "0.3"  

[build-dependencies]
tonic-build = "0.11.0"

2.2 创建文件proto/greeter.proto, 内容如下:

syntax = "proto3";

package greeter;

// The greeting service definition.
service Greeter {
  // Sends a stream of greetings
  rpc SayHello (HelloRequest) returns (stream 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;
}

2.3 添加build.rs文件, 内容如下:

use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let protos = [
        "proto/greeter.proto",
    ];
    tonic_build::configure().compile(&protos, &["proto/"])?;
    Ok(())
}

2.4 项目结构如下:

在这里插入图片描述

2.5 编译proto文件

cargo build

3.0 处理服务

3.1 项目引入

编辑src/lib.rs, 内容如下:

pub mod hello {
    tonic::include_proto!("greeter");
}

3.2 添加src/server.rs, 内容如下:

HelloService 是实现hello的service

use tonic::{transport::Server, Request, Response, Status};
use futures::Stream;  // Import Stream trait from futures crate
use tokio_stream::{wrappers::ReceiverStream};
use tokio::sync::mpsc;
use std::pin::Pin;
use tonic::async_trait;
use grpc_stream_demo::hello::greeter_server::{Greeter, GreeterServer};
use grpc_stream_demo::hello::{HelloRequest, HelloReply};

#[derive(Debug, Default)]
pub struct MyGreeter;

#[async_trait]
impl Greeter for MyGreeter {

    type SayHelloStream = Pin<Box<dyn Stream<Item = Result<HelloReply, Status>> + Send>>;

    // Implement the streaming SayHello method
    async fn say_hello(
        &self,
        request: Request<HelloRequest>,
    ) -> Result<Response<Self::SayHelloStream>, Status> {
        let name = request.into_inner().name;

        // Create a channel for streaming responses
        let (tx, rx) = mpsc::channel(4);

        // Spawn a task to send greetings through the channel
        tokio::spawn(async move {
            for i in 1..=5 {
                let message = format!("Hello, {}! This is greeting number {}", name, i);
                let reply = HelloReply { message };

                // Send each reply via the channel
                if let Err(_) = tx.send(Ok(reply)).await {
                    break;
                }

                // Simulate a delay between greetings
                tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            }
        });

        // Convert the receiver into a stream
        let stream = ReceiverStream::new(rx);

        // Return the stream as the response
        Ok(Response::new(Box::pin(stream)))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse().unwrap();
    let greeter = MyGreeter::default();

    println!("Greeter server listening on {}", addr);

    Server::builder()
        .add_service(GreeterServer::new(greeter))
        .serve(addr)
        .await?;
    Ok(())
}

3.3 添加src/client.rs, 内容如下:

HelloService 是实现hello的service

use grpc_stream_demo::hello::greeter_client::GreeterClient;
use grpc_stream_demo::hello::{HelloRequest, HelloReply};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = GreeterClient::connect("http://[::1]:50051").await?;

    let request = tonic::Request::new(HelloRequest {
        name: "Alice".into(),
    });

    let mut stream = client.say_hello(request).await?.into_inner();

    while let Some(reply) = stream.message().await? {
        println!("Received: {}", reply.message);
    }

    Ok(())
}

5 运行服务

5.1 修改Cargo.toml, 添加运行bin配置, 内容如下:

[package]
name = "grpc-stream-demo"
version = "0.1.0"
edition = "2021"

[[bin]]
name="client"
path="src/client.rs"


[[bin]]
name="server"
path="src/server.rs"

[dependencies]
tonic = "0.12.3"
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "full"] }
prost = "0.13.3"
tokio-stream = "0.1"
futures = "0.3"  # Add this line for futures

[build-dependencies]
tonic-build = "0.11.0"

5.2 运行server

cargo run --bin server

结果如下:
在这里插入图片描述

5.3 运行client, 测试

重新打开一个命令行, 进入项目根目录, 然后执行:

cargo run --bin client

结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值