.Net Core gRPC入门(三)——双向流

常见的请求过程是:客户端发起请求 > 服务器处理请求 > 服务器返回请求,客户端只发送一次数据,服务器也只返回一次数据。而双向流可以在一次请求中让客户端发送多次数据,服务端返回多次数据


一、添加双向流


1. 修改greet.proto

替换为以下内容:

syntax = "proto3";

option csharp_namespace = "GrpcDemo.Service";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
  rpc Bothway(stream ToMessage) returns(stream BackMessage);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

message ToMessage{
	string message = 1;
}

message BackMessage{
	string message = 1;
}

添加了一个Bothway方法,该方法参数为ToMessage,返回BackMessage。使用 stream 修饰,声明为流式传输


2. 实现Bothway

修改 GrpcDemo.Service > GreeterService.cs,实现Bothway方法:

/// <summary>
/// 双向流
/// </summary>
/// <param name="requestStream">请求流</param>
/// <param name="responseStream">响应流</param>
/// <param name="context">上下文</param>
/// <returns></returns>
public override async Task Bothway(IAsyncStreamReader<ToMessage> requestStream, IServerStreamWriter<BackMessage> responseStream, ServerCallContext context)
{
    while (!context.CancellationToken.IsCancellationRequested && await requestStream.MoveNext())
    {
        string msg = requestStream.Current.Message;
        Console.WriteLine($"加载模块:{msg}");
        await Task.Delay(500);
        if (!context.CancellationToken.IsCancellationRequested)
        {
            await responseStream.WriteAsync(new BackMessage()
            {
                Message = $"{msg}模块加载完成"
            });
        }
    }
}

3. 编写客户端

修改 GrpcDemo.Client > Program.cs

private const string ServiceAddress = "https://localhost:5001";

static void Main(string[] args)
{
    var task = Bothway();
    task.Wait();
    Console.ReadKey();
}

//发送模块的个数
const int count = 10;

public async static Task Bothway()
{
	//创建Grpc通道
    var channel = GrpcChannel.ForAddress(ServiceAddress);
    //创建Greeter客户端
    var client = new Greeter.GreeterClient(channel);
    //创建双向流对象
    var bothway = client.Bothway();
    //CancellationTokenSource 管理是否关闭流
    //CancellationTokenSource.CancelAfter() 规定时间关闭流
    //CancellationTokenSource.Cancel() 立即关闭流
    var cts = new CancellationTokenSource();
    //响应事件
    var backTask = Task.Run(async () =>
    {
        int current = 0;
        try
        {
            //从响应流获取数据(cts.Token: 是否关闭流)
            while (await bothway.ResponseStream.MoveNext(cts.Token))
            {
                current++;
                var back = bothway.ResponseStream.Current;
                Console.WriteLine($"{back.Message},加载进度{((double)current / count) * 100}%");
                if (current >= 5)
                {
                    //关闭流
                    cts.Cancel();
                }
            }
        }
        //关闭流异常捕获
        catch (RpcException ex) when (ex.StatusCode == StatusCode.Cancelled)
        {
            Console.WriteLine("Stream cancelled.");
        }
    });

    for (int i = 0; i < count; i++)
    {
        //请求流写入数据
        await bothway.RequestStream.WriteAsync(new ToMessage()
        {
            Message = i.ToString()
        });
    }

    //等待发送完成
    await bothway.RequestStream.CompleteAsync();

    Console.WriteLine("加载模块发送完毕");
    Console.WriteLine("等待加载...");

    //等待响应完成
    await backTask;

    Console.WriteLine("模块已全部加载完毕");
}

注意:以上代码如果出现缺少引用找不到类的问题,请重新生成解决方案或项目。


二、运行并查看结果

输出:
输出

可以看到一个双向流的过程了,加载模块5完成后关闭流,输出了Stream cancelled


参考资料

微软官方Grpc教程
Grpc英文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值