.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);
}
}
}
浙公网安备 33010602011771号