翼度科技»论坛 编程开发 .net 查看内容

第41篇 Grpc实现客户端与服务端高效通信

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
grpc的确是现在最流行的跨平台间的通信技术。远不止.net上使用。grpc是谷歌公司推出的跨语言平台之间的通信技术。和webapi不同的是,可以使用自己的语言和另一种语言进行通信。

简单来讲就是首先使用一种Proto的协议文件,可以生成客户端和服务端两种文件。客户端和服务端可以使用任意的语言。grpc工具会将proto编译成任何一种语言。
比方说c#和java进行通讯。这时首先确认谁作server谁做client。然后使用grpc tools编译成c#类库和java的jar包,再引入到各自的项目,这时在c#引用的grpc tools生成的dll里就有proto文件中生成的方法。而java中的jar包也会有对应的方法。当然在这之前需要在proto中规定两端使用的api方法。也就是先生成proto文件约定两端之间调用的方法名称,参数,及参数类型。然后就可以完成跨语言之间的协同开发。可以一个java server端,对应于多个不同语言的client端,如python、nodejs、c#等。也可以一个server端如rust server端,对应多个相同的客户端如php等。非常的灵活。
grpc可以说是一种非常高效的跨平台的通讯方案。因为它已经支持是http2。未来会支持基于udp的http3真正实现异步io。
下面我通过一个框架搭建的demo进行演示
1.GrpcProject项目框架

框架分为客户端和服务端,以及一些公共类库,使得框架完善

1.1 GrpcClient_Console客户端,采用控制台

通过客户端连接服务端,发送数据
主要代码实现如下
  1. public class Program
  2.         {
  3.                 static async Task Main(string[] args)
  4.                 {
  5.                         Channel channel = new("localhost:5099", ChannelCredentials.Insecure);
  6.                         try
  7.                         {
  8.                                 Console.WriteLine("这个应用是客户端,正在连接远程服务端...");
  9.                                 await channel.ConnectAsync();
  10.                                 Console.WriteLine("服务端连接成功");
  11.                                 Console.WriteLine("Successfully connected to the server!");
  12.                                 Console.WriteLine("First name?");
  13.                                 var name = Console.ReadLine();
  14.                                 Console.WriteLine("Last name? ");
  15.                                 var lastName = Console.ReadLine();
  16.                                 var request = new CreatePersonRequest
  17.                                 {
  18.                                         FirstName = name,
  19.                                         LastName = lastName
  20.                                 };
  21.                                 var client = new PeopleService.PeopleServiceClient(channel);
  22.                                 var response = await client.CreatePersonAsync(request);
  23.                                 Console.WriteLine($"{response.FirstName} {response.LastName} has been created " +
  24.                                         $"on the server! (id = {response.Id})");
  25.                                 Console.WriteLine("Press enter to close the client");
  26.                                 Console.ReadLine();
  27.                         }
  28.                         catch (Exception ex)
  29.                         {
  30.                                 Console.WriteLine("An error occurred: " + ex.ToString());
  31.                                 Console.ReadLine();
  32.                         }
  33.                         finally
  34.                         {
  35.                                 if (channel is not null)
  36.                                 {
  37.                                         await channel.ShutdownAsync();
  38.                                 }
  39.                         }
  40.                 }
  41.         }
复制代码
2.GrpcServer_Console服务端,采用控制台

服务端可以接送客户端发送消息,并写入数据库
主要是这三个类Program,PeopleServiceImpl,ServerDbContext
通过这三个类之间的调用,可以生成数据库,数据写入库,数据库采用sqlite
  1. internal class Program
  2.         {
  3.                 static async Task Main(string[] args)
  4.                 {
  5.                         new ServerDbContext().Database.EnsureCreated();
  6.                         Server server = new()
  7.                         {
  8.                                 Ports = { new ServerPort("localhost", 5099, ServerCredentials.Insecure) },
  9.                                 Services = { PeopleService.BindService(new PeopleServiceImpl()) }
  10.                         };
  11.                         try
  12.                         {
  13.                                 Console.WriteLine("这应用是服务端,正在启动服务端...");
  14.                                 server.Start();
  15.                                 Console.WriteLine("服务端启动成功");
  16.                                 Console.WriteLine("Press enter to close the server");
  17.                                 Console.ReadLine();
  18.                         }
  19.                         catch (Exception ex)
  20.                         {
  21.                                 Console.WriteLine("An error occurred: " + ex.ToString());
  22.                         }
  23.                         finally
  24.                         {
  25.                                 if (server is not null)
  26.                                 {
  27.                                         await server.ShutdownAsync();
  28.                                 }
  29.                         }
  30.                 }
  31.         }
  32. public class PeopleServiceImpl : PeopleServiceBase
  33.         {
  34.                 public override async Task<Person> CreatePerson(
  35.                         CreatePersonRequest request,
  36.                         ServerCallContext context)
  37.                 {
  38.                         using var ctx = new ServerDbContext();
  39.                         var dbPerson = new Person
  40.                         {
  41.                                 LastName = request.LastName,
  42.                                 FirstName = request.FirstName
  43.                         };
  44.                         ctx.People.Add(dbPerson);
  45.                         await ctx.SaveChangesAsync();
  46.                         return new Person
  47.                         {
  48.                                 LastName = request.LastName,
  49.                                 FirstName = request.FirstName,
  50.                                 Id = dbPerson.Id
  51.                         };
  52.                 }
  53.         }
  54. public class ServerDbContext : DbContext
  55.         {
  56.                 public DbSet<Person> People { get; set; }
  57.                 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  58.                 {
  59.                         optionsBuilder.UseSqlite("Filename = data.db");
  60.                 }
  61.         }
复制代码
3.共用类库

GrpcProtos :用于存放Proto文件
AbstractDAL :用于数据库操作抽象类
DBEntity : 存放数据库表实体
EntityMap :用于grpc通信实体与数据库实体之间相互转换的帮助类
GrpcEntity :存放grpc通信的参数实体,响应返回实体等;
4.demo启动演示

先启动服务端:

再启动客户端,如果客户端连上了服务端,效果如下

分别按指示输入:

服务端的数据库会新增people数据


到此,演示算成功,客户端与服务端成功通信,并且操作数据可以落库。
感兴趣的朋友可以访问我的gitee代码库:https://gitee.com/chenshibao/grpc-project

来源:https://www.cnblogs.com/chenshibao/p/18494490
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具