.NET 客户端调用 gRPC 服务的四种通信方式

  • 一元调用
  • 客户端流模式
  • 双向流模式
  • 服务端流模式

一元调用

一元调用从客户端发送请求消息开始。 服务完成后,将返回响应消息。

客户端流模式

客户端流式处理调用在客户端发送消息的情况下启动。 客户端可以选择发送发送消息RequestStream.WriteAsync。 当客户端已经完成发送消息RequestStream.CompleteAsync时,应调用来通知服务。 当服务返回响应消息时,调用完成。

双向流模式

双向流式处理调用在客户端发送消息的情况下启动。 客户端可以选择通过RequestStream.WriteAsync发送消息。 可以通过或ResponseStream.ReadAllAsync()访问从服务流式处理ResponseStream.MoveNext()的消息。 当没有更多消息时ResponseStream ,双向流式处理调用完成。

服务端流模式

服务器流式处理调用会从客户端发送请求消息开始。 ResponseStream.MoveNext()读取从服务传输的消息。 ResponseStream.MoveNext() 返回false时,服务器流调用已完成。

代码 Protos

syntax = "proto3";

option csharp_namespace = "GrpcService1";

import "google/protobuf/empty.proto";
package Count;

service Counter{
	rpc AddStream(stream NumberRequest) returns (ResultReply);
	rpc Add(TwoNumberRequest) returns (ResultReply);
	rpc AddTwoStream(stream NumberRequest) returns (stream ResultReply);
	rpc GetInfo(google.protobuf.Empty) returns (ResultReply);
}

message TwoNumberRequest{
	int32 num1=1;
	int32 num2=2;
}

message NumberRequest{
	int32 num=1;
}

message ResultReply{
	int32 num=1;
}

代码 服务端

   public class CountService : Counter.CounterBase
    {
        private readonly ILogger<CountService> _logger;
        public CountService(ILogger<CountService> logger)
        {
            _logger = logger;
        }
        //一元请求
        public override Task<ResultReply> Add(TwoNumberRequest request, ServerCallContext context)
        {
            return Task.FromResult(new ResultReply() { Num = request.Num1 + request.Num2 });
        }

        /// <summary>
        /// 双向流请求
        /// </summary>
        /// <param name="requestStream"></param>
        /// <param name="responseStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task AddTwoStream(IAsyncStreamReader<NumberRequest> requestStream, IServerStreamWriter<ResultReply> responseStream, ServerCallContext context)
        {
            int result = 0;
            while (await requestStream.MoveNext())
            {
                result += requestStream.Current.Num;
                await responseStream.WriteAsync(new ResultReply() { Num = result });
                await Task.Delay(1000);
            }
            await responseStream.WriteAsync(new ResultReply() { Num = result*1000 }); 
        }

        /// <summary>
        /// 客户端流程求
        /// </summary>
        /// <param name="requestStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task<ResultReply> AddStream(IAsyncStreamReader<NumberRequest> requestStream, ServerCallContext context)
        {
            int result = 0;
            while (await requestStream.MoveNext())
            {
                result += requestStream.Current.Num;
            }
            return await Task.FromResult(new ResultReply() { Num = result });
        }

        public override Task<ResultReply> GetInfo(Empty request, ServerCallContext context)
        {
            return base.GetInfo(request, context);
        }
    }

代码 客户端

  class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var channel = GrpcChannel.ForAddress("https://localhost:5001");
            var client = new GrpcService1.Counter.CounterClient(channel);
            Console.WriteLine("一元请求");
            var result = client.Add(new GrpcService1.TwoNumberRequest() { Num1 = 1, Num2 = 1 });
            Console.WriteLine($"一元请求结果{result.Num}");
            Console.WriteLine("-----------------------");
            Console.WriteLine("客户端流请求");
            var clientStream = client.AddStream();
            for (var i = 0; i < 10; i++)
            {
                await clientStream.RequestStream.WriteAsync(new GrpcService1.NumberRequest() { Num = i });
            }
            clientStream.RequestStream.CompleteAsync();
            var resut1 = await clientStream;
            Console.WriteLine($"客户端流请求结果{resut1.Num}");
            Console.WriteLine("-----------------------");
            Console.WriteLine("双向流");
            var doubleStream = client.AddTwoStream();
            Task.Run(async () =>
            {
                await foreach (var resp in doubleStream.ResponseStream.ReadAllAsync())
                {
                    Console.WriteLine($"中间结果:{resp.Num}");
                }
            });
            for (var i = 0; i < 10; i++)
            {
               await doubleStream.RequestStream.WriteAsync(new GrpcService1.NumberRequest() { Num = i });
            }
            doubleStream.RequestStream.CompleteAsync();

            Console.ReadLine();
        }
    }

[查看原文] .net core gRPC 一元,流通信 --- (单工 双工) - 我是小虫 - 博客园 (cnblogs.com)