.net Grpc

Grpc 对应的类型

 使用空类型 需要引用

import "google/protobuf/empty.proto";

空类型

google.protobuf.Empty

数组类型

repeated

搞之前 需创建 Grpc 服务项目

建立 Proto 存根

 存根中的

版本

syntax = "proto3";

命名空间

option csharp_namespace = "DanService";

包名

package dan;

服务名

service Dan

定义参数方式 

message QueryUserName
{
   string UserName =1;
}

 

定义函数方式

rpc GetUserAll(google.protobuf.Empty) returns(QueryUerAllReplay);  

服务端代码

syntax = "proto3";
option csharp_namespace = "DanService";
package dan;
import "google/protobuf/empty.proto";
service Dan {
  //单向流 客户端 请求 服务端 返回流
  rpc GetUser (google.protobuf.Empty) returns (stream UserEntityReply);
  //单向流 客户端 请求 服务端 客户端传入流 
  rpc UpDateUser(stream UpdateUserRequst) returns (UpdateUserReplay);
  //双向流
  rpc InsertUser(stream UserInsertRequst) returns(stream UserInsertReply);
  //双向非流 请求传值 返回值
  rpc GetUserOne(QueryUserName) returns(QueryUserReplay);
  //单向非流 不传值 返回值
  rpc GetUserAll(google.protobuf.Empty) returns(QueryUerAllReplay);  
}
message QueryUserName
{
   string UserName =1;
}
message QueryUserReplay
{
  UserEntity UserEntity =1;
}
message QueryUerAllReplay
{
  repeated UserEntity UserEntities =1;  
}
message UpdateUserRequst
{
  UserEntity user =1;
}
message UpdateUserReplay{
  bool isUpdateResult =1;
}
message UserInsertRequst{
  string message =1;
  UserEntity user =2;
}
message UserInsertReply{
  bool isReuslt=1;
}
message UserEntityReply {    
  UserEntity user = 1;
  string message = 2;
}
message UserEntity{
  string name =1;
  int32 age =2;
}

 

实现

 

 

using DanService;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;

namespace GrpcService1.Services
{
    public class DanClientService : Dan.DanBase
    {
        /// <summary>
        /// 单向流 客户端 请求 服务端 返回流
        /// </summary>
        /// <param name="request"></param>
        /// <param name="responseStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GetUser(Empty request, IServerStreamWriter<UserEntityReply> responseStream, ServerCallContext context)
        {
            await responseStream.WriteAsync(new UserEntityReply { Message = "helloworld", User = new UserEntity { Name = "小明", Age = 10 } });
        }

        /// <summary>
        /// 单向流 客户端 请求 服务端 客户端传入流 
        /// </summary>
        /// <param name="requestStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task<UpdateUserReplay> UpDateUser(IAsyncStreamReader<UpdateUserRequst> requestStream, ServerCallContext context)
        {
            UpdateUserRequst userRequst = null;
            await Task.Run(async () =>
            {
                await foreach (var item in requestStream.ReadAllAsync())
                {
                    userRequst = item;
                    Console.WriteLine(userRequst);
                }
            });
            return new UpdateUserReplay { IsUpdateResult = true };
        }

        /// <summary>
        /// 双向流
        /// </summary>
        /// <param name="requestStream"></param>
        /// <param name="responseStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task InsertUser(IAsyncStreamReader<UserInsertRequst> requestStream, IServerStreamWriter<UserInsertReply> responseStream, ServerCallContext context)
        {
            UserInsertRequst userInsert = null;
            var task = Task.Run(async () =>
            {
                await foreach (var message in requestStream.ReadAllAsync())
                {
                    userInsert = message;
                }
            });
            await task;
            await responseStream.WriteAsync(new UserInsertReply { IsReuslt = true });
        }
        /// <summary>
        /// 单向非流 不传值 返回值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task<QueryUerAllReplay> GetUserAll(Empty request, ServerCallContext context)
        {
            QueryUerAllReplay queryUerAll = new QueryUerAllReplay();
            queryUerAll.UserEntities.Add(new UserEntity { Name = "你好", Age = 1 });
            queryUerAll.UserEntities.Add(new UserEntity { Name = "越来越好", Age = 2 });
            return Task.FromResult(queryUerAll);
        }
        /// <summary>
        /// 双向非流 请求传值 返回值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task<QueryUserReplay> GetUserOne(QueryUserName request, ServerCallContext context)
        {
            string username = request.UserName;
            Console.WriteLine(username);
            QueryUserReplay userReplay = new QueryUserReplay { UserEntity = new UserEntity { Age = 90, Name = $"返回人名:{username}" } };
            return Task.FromResult(userReplay);
        }
    }
}

  

 

 

客户端代码

建立一个简单webapi

将存根文件拷贝到客户端中

 

修改存根项目文件 为client 这里只能手动修改 不会自动修改Client

  <ItemGroup>
    <Protobuf Include="Protos\counter.proto" GrpcServices="Client" />
    <Protobuf Include="Protos\race.proto" GrpcServices="Client" />
    <Protobuf Include="Protos\testdanclient.proto" GrpcServices="Client" />
    <Protobuf Include="Protos\user.proto" GrpcServices="Client" />
  </ItemGroup>

  

服务端的是Server 这里要注意

 

注入 存根的 对象 这里写有些罗嗦 需要封装 以后再说

 

using DanService;
using GrpcCountService;
using Microsoft.AspNetCore.Mvc;
using Race;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using UserService;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddGrpcClient<Userproto.UserprotoClient>(options =>
{
    options.Address = new Uri("http://localhost:5190");
});
builder.Services.AddGrpcClient<Counter.CounterClient>(options =>
{
    options.Address = new Uri("http://localhost:5190");
});
builder.Services.AddGrpcClient<Racer.RacerClient>(options =>
{
    options.Address = new Uri("http://localhost:5190");
});
builder.Services.AddGrpcClient<Dan.DanClient>(options =>
{
    options.Address = new Uri("http://localhost:5190");
});

builder.Services.Configure<SwaggerGenOptions>(options =>
{
    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
    {
         Title ="测试",
    });

    string xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,Assembly.GetExecutingAssembly().GetName().Name + ".xml");
    options.IncludeXmlComments(xmlPath, true);
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
        options.RoutePrefix = "";
    });
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

 

接口调用 的实现 以下是demo 不必在一 代码细节

特别注意 请求流的写法 需要 写  await channel.RequestStream.CompleteAsync();

 await channel.RequestStream.WriteAsync(new UserInsertRequst { Message = "添加用户", User = new UserEntity { Age = 1, Name = "晓东" } });
 await channel.RequestStream.CompleteAsync();
using DanService;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static DanService.Dan;

namespace TestGRPCClientWebAPI.Controllers
{
    /// <summary>
    /// Grpc 双向流 非流 
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class TestDanController : ControllerBase
    {

        private readonly DanClient danClient;

        public TestDanController(DanClient danClient)
        {
            this.danClient = danClient;
        }

        /// <summary>
        /// 获取用户 单向流 客户端 请求 服务端 返回流
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetUser")]
        public async Task<ActionResult> GetUser()
        {
            using var call = danClient.GetUser(new Empty());
            DanService.UserEntityReply reply = null;
            await Task.Run(async () =>
           {
               await foreach (var message in call.ResponseStream.ReadAllAsync())
               {
                   reply = message;
               }
           });
            return Ok(reply);
        }

        /// <summary>
        /// 添加用户 双向流
        /// </summary>
        /// <returns></returns>
        [HttpPost("InsertUser")]
        public async Task<ActionResult> InsertUser()
        {
            var channel = danClient.InsertUser();
            await channel.RequestStream.WriteAsync(new UserInsertRequst { Message = "添加用户", User = new UserEntity { Age = 1, Name = "晓东" } });
            await channel.RequestStream.CompleteAsync();
            UserInsertReply insertReply = null;
            var task = Task.Run(async () =>
             {
                 await foreach (var item in channel.ResponseStream.ReadAllAsync())
                 {
                     insertReply = item;
                 }
             });
            await task;
            return Ok(insertReply);
        }

        /// <summary>
        /// 更新 单向流 客户端 请求 服务端 客户端传入流 
        /// </summary>
        /// <returns></returns>
        [HttpPut("UpDateUser")]
        public async Task<ActionResult> UpDateUser()
        {
            var channel = danClient.UpDateUser();
            await channel.RequestStream.WriteAsync(new UpdateUserRequst { User = new UserEntity { Age = 22, Name = "22" } });
            await channel.RequestStream.CompleteAsync();
            var replay = await channel.ResponseAsync;
            return Ok(replay);
        }

        /// <summary>
        /// 获取一个用户 双向非流 请求传值 返回值
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetOne/{userName}")]
        public ActionResult GetOne([FromRoute] string userName)
        {
            var reuslt = danClient.GetUserOne(new QueryUserName { UserName = userName });
            return Ok(reuslt);
        }
        /// <summary>
        /// 获取所有用户 单向非流 不传值 返回值
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetUserAll")]
        public ActionResult GetUserAll()
        {

            var result = danClient.GetUserAllAsync(new Empty());
            var list = result.ResponseAsync.Result.UserEntities;
            return Ok(list);
        }

    }
}

  

 

posted on 2023-12-13 11:44  是水饺不是水饺  阅读(35)  评论(0)    收藏  举报

导航