基于C#的GRPC

GRPC

gRPC(gRPC Remote Procedure Call)是由Google开发的高性能、跨语言的远程过程调用框架。它基于HTTP/2协议进行通信,支持多种编程语言,包括C++, C#, Java, Python等,使不同语言的应用程序可以通过远程调用相互通信。

1.关键特点和用途:

  1. 高性能:gRPC采用了HTTP/2协议,具有低延迟、高吞吐量和复用连接的特点。这使得它非常适合于需要高性能通信的应用程序。
  2. 跨语言支持:gRPC支持多种编程语言,允许不同语言的应用程序之间进行跨语言通信。这使得它在微服务架构中非常有用,因为不同的服务可以使用不同的编程语言实现。
  3. IDL(Interface Definition Language):gRPC使用ProtoBuf(Protocol Buffers)作为IDL,允许您定义服务接口和消息类型。这提供了强类型的通信,使得通信更加清晰和高效。
  4. 多种通信类型:gRPC支持不同类型的通信,包括请求-响应、服务器流、客户端流和双向流。这允许您选择最适合您应用程序需求的通信方式。
  5. 自动化代码生成:通过ProtoBuf定义服务接口和消息类型,gRPC工具会自动生成客户端和服务器端的代码,这样可以大大减少开发工作量。
  6. 认证和安全:gRPC支持各种认证和安全机制,包括SSL/TLS,OAuth等,以确保通信的安全性。
  7. 服务发现:gRPC可以与服务发现工具(如Consul、etcd)集成,从而实现动态服务发现和负载均衡。
  8. 可扩展性:gRPC是一个可扩展的框架,支持各种自定义扩展和中间件。

2.GRPC思路

Grpc类似于一种协议,遵循网络通讯,以.proto文件为协议模板进行客户端与服务端的交互开发,不限制客户端和服务端的代码语言风格.也可以在服务端与客户端使用不同的语言开发

3.编写.proto文件

在这里插入图片描述

// Protocol Buffers 语法版本 proto3 版本
syntax = "proto3";
// 定义了消息类型和服务的包名,类似于命名空间,用于避免命名冲突。
package Calculator;
// 定义了一个 gRPC 服务。在大括号中,您可以列出服务方法的定义。
service CalculatorService 
{// 定义了一个服务方法。rpc 表示定义一个远程过程调用(RPC)方法。MyMethod 是方法的名称,MyRequest 是输入参数类型,MyResponse 是输出参数类型。rpc MyMethod (MyRequest) returns (MyResponse);// 服务器流式方法rpc ServerStreamingMethod(Request1) returns (stream Response1);// 客户端流式方法rpc ClientStreamingMethod(stream Request2) returns (Response2);// 双向流式方法rpc BidirectionalStreamingMethod(stream Request3) returns (stream Response3);
}
message MyRequest 
{repeated int32 num = 10;
}
message MyResponse 
{repeated string strs = 10;
}message Request1
{string Message = 1;
}
message Response1
{string Message = 1;
}
message Request2
{string Message = 1;
}
message Response2
{string Message = 1;
}
message Request3
{string Message = 1;
}
message Response3
{string Message = 1;
}
syntax = "proto3";package Calculator;import "Protos/Calculator.proto";service FirstService {rpc MyMethod (MyRequest1) returns (MyResponse);
}
message MyRequest1 
{repeated int32 num = 10;
}

多个.proto文件间是可以调用的

在这里插入图片描述

4.添加.proto文件生成的文件编写服务端和客户端代码

在这里插入图片描述

.proto文件生成的文件位置 添加到客户端和服务端

5.服务端代码

using Calculator;
using Grpc.Core;class CalculatorServiceImpl : CalculatorService.CalculatorServiceBase
{/// <summary>/// 发布响应/// </summary>/// <param name="request"></param>/// <param name="context"></param>/// <returns></returns>public override async Task<MyResponse> MyMethod(MyRequest request, ServerCallContext context){MyResponse myResponse = new MyResponse();foreach (int i in request.Num){myResponse.Strs.Add(i.ToString());}return myResponse;}/// <summary>/// 服务器流(Server Streaming)/// </summary>/// <param name="request"></param>/// <param name="responseStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task ServerStreamingMethod(Request1 request, IServerStreamWriter<Response1> responseStream, ServerCallContext context){for (int i = 0; i < 10; i++){Response1 response = new Response1 { Message = request.Message + $"Message {i}" };await responseStream.WriteAsync(response);await Task.Delay(500); // 模拟每秒发送一次数据}}/// <summary>/// 客户端流(Client Streaming)/// </summary>/// <param name="requestStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task<Response2> ClientStreamingMethod(IAsyncStreamReader<Request2> requestStream, ServerCallContext context){string str = "";while (requestStream.MoveNext().Result){str += requestStream.Current.Message;Console.WriteLine(requestStream.Current.Message);}return new Response2 { Message = str };}/// <summary>/// 双向流(Bidirectional Streaming)/// </summary>/// <param name="requestStream"></param>/// <param name="responseStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task BidirectionalStreamingMethod(IAsyncStreamReader<Request3> requestStream, IServerStreamWriter<Response3> responseStream, ServerCallContext context){while (requestStream.MoveNext().Result){// 处理客户端发送的请求Console.WriteLine(requestStream.Current.Message);Response3 response = new Response3 { Message = requestStream.Current.Message + "abc" };await responseStream.WriteAsync(response); // 发送响应await Task.Delay(500);}}}class Program
{static void Main(string[] args){const int Port = 50051;Server server = new Server{Services = { CalculatorService.BindService(new CalculatorServiceImpl()) },Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }};server.Start();Console.WriteLine("Calculator server listening on port " + Port);Console.WriteLine("Press any key to stop the server...");Console.ReadKey();server.ShutdownAsync().Wait();}
}

6.客户端代码

using Calculator;
using Grpc.Core;class Program
{const string ServerAddress = "localhost";const int Port = 50051;static void Main(string[] args){MyMethod();ServerStreamingMethod();SelfIncreaseClient();BidirectionalStreamingMethod();Console.WriteLine("Press any key to exit...");Console.ReadKey();}/// <summary>/// 发布响应/// </summary>private static void MyMethod(){Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);var client = new CalculatorService.CalculatorServiceClient(channel);MyRequest myRequest = new MyRequest { Num = { 1, 2, 3, 4 } };MyResponse myResponse = client.MyMethod(myRequest);Console.WriteLine($"Result: {myResponse.Strs}");channel.ShutdownAsync().Wait();}/// <summary>/// 服务器流(Server Streaming)/// </summary>private static void ServerStreamingMethod(){Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);var client = new CalculatorService.CalculatorServiceClient(channel);Request1 request1 = new Request1 { Message = "ceshi" };AsyncServerStreamingCall<Response1> response1s = client.ServerStreamingMethod(request1);while (response1s.ResponseStream.MoveNext().Result){Console.WriteLine(response1s.ResponseStream.Current.Message);}channel.ShutdownAsync().Wait();}/// <summary>/// 客户端流(Client Streaming)/// </summary>private static async void SelfIncreaseClient(){Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);var client = new CalculatorService.CalculatorServiceClient(channel);var call = client.SelfIncreaseClient();for (int i = 0; i < 10; i++){await call.RequestStream.WriteAsync(new Request2() { Message = $"第{i}个" });await Task.Delay(500);}await call.RequestStream.CompleteAsync();Console.WriteLine($"Result: {call.ResponseAsync.Result.Message}");channel.ShutdownAsync().Wait();}/// <summary>/// 双向流(Bidirectional Streaming)/// </summary>private static async void BidirectionalStreamingMethod(){Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);var client = new CalculatorService.CalculatorServiceClient(channel);var call = client.BidirectionalStreamingMethod();for (int i = 1; i <= 5; i++){// 发送请求await call.RequestStream.WriteAsync(new Request3 { Message = i.ToString() }); await Task.Delay(500);}await call.RequestStream.CompleteAsync();while (call.ResponseStream.MoveNext().Result){// 处理服务器发送的响应Console.WriteLine(call.ResponseStream.Current.Message);}channel.ShutdownAsync().Wait();}
}

7.Demo示例

在这里插入图片描述

在这里插入图片描述

2023/11/7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/184156.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#创建Windows Service(Windows 服务)基础教程

Windows Service这一块并不复杂&#xff0c;但是注意事项太多了&#xff0c;网上资料也很凌乱&#xff0c;偶尔自己写也会丢三落四的。所以本文也就产生了&#xff0c;本文不会写复杂的东西&#xff0c;完全以基础应用的需求来写&#xff0c;所以不会对Windows Service写很深入…

软件工程第十周

测试过程 单元测试 注意出错处理&#xff01;单元测试的数据处理部分请见Junit 单元测试之错误和异常处理-CSDN博客 单元测试准则 白盒&#xff1a;对系统结构非常清楚&#xff01;就像大题注重过程。 单元测试的测试环境 一定要保证整个环境是完整的&#xff0c;尽管可能没…

论文阅读——变化检测

Viewpoint Integration and Registration with Vision Language Foundation Model for Image Change Understanding 只有fused adapter image encoder, viewpoint registration flow, semantic emphasizing module, 和 fully connected layer 训练&#xff0c;其他参数冻结。 F…

数据结构(c语言版) 队列

链队列 要求&#xff1a;实现链队列的创建、初始化、入队、出队 &#xff08;先进先出&#xff09; 代码 // // Created by My.cy on 2023/10/19. // //链队列 创建、初始化、入队、出队 先进先出#include <stdio.h> #include <malloc.h>//定义结构体 struct…

【Android】android studio 怎么下载NDK

序言 新版的android studio在【Project Structure】里面的NDK路径是灰色的&#xff0c;无法点击&#xff0c;导致找不到ndk路径&#xff0c;也无法添加ndk。 下载方法 去这里找&#xff0c;一定要点这个按钮才能出现ndk。 下载之后&#xff0c;要在这个文件里面添加ndk路径

【JS】判断字符串是否为 url 的方法

文章目录 用法解析 用法解析 当你传递一个字符串给 URL 构造函数时: 如果字符串是一个有效的 URL&#xff0c;它将返回一个新的 URL 对象。否则&#xff0c;它将返回一个错误。 const url new URL("https://www.baidu.com/"); console.log(url);函数封装&#xf…

visual studio Python 配置QGIS(qgis)教程

visual studio Python 配置QGIS&#xff08;qgis&#xff09;教程 这个教程全网独一份啊&#xff0c;博主是自己摸索出来的。 visual studio Python 配置QGIS&#xff08;qgis&#xff09;环境一共分为两部&#xff1a; 第一步安装QGIS&#xff1a; 下载链接如下 https://www…

基于FPGA的模板匹配红外目标跟踪算法设计

为什么要写这篇文章 我写这篇文章的原因是一天在B站看到了一个大神发的视频是关于跟踪一个无人机的&#xff0c;看到作者跟网友的回复说是用的图像匹配算法&#xff0c;我就在网上搜索相关资料&#xff0c;最终找到一篇文献。文献中对该算法的评价很高&#xff0c;满足制导系统…

在湖北考一个安全员c3住建厅安全员c证持证上岗

在湖北考一个安全员c3住建厅安全员c证持证上岗 建筑施工行业专职安全员&#xff0c;从事建筑行业安全或者是安全管理方面的工作&#xff0c;都需要有安全员C证&#xff0c;湖北省安全员C3是属于安全员C证中的一种。 安全员C3证涵盖范围广&#xff0c;大部分报考人员都是选择C…

面试题:线上MySQL的自增id用尽怎么办?

文章目录 前言表定义自增值idInnoDB系统自增row_idXidInnodb trx_id InnoDB数据可见性的核心思想为什么要加248&#xff1f;为何只读事务不分配trx_id&#xff1f;thread_id 总结 前言 MySQL的自增id都定义了初始值&#xff0c;然后不断加步长。虽然自然数没有上限&#xff0c…

竞赛 深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习加…

Web服务器实战

网站需求 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个网站目录分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教学资料 www…

Spring Boot创建多模块项目

创建一个普通的Spring Boot项目, 然后只留下 pom.xml 剩下的都删掉 删除多余标签 标识当前为父模块 创建子模块 删除子模块中多余标签 声明父模块 在父模块中声明子模块

【MongoDB-Redis-MySQL-Elasticsearch-Kibana-RabbitMQ-MinIO】Java全栈开发软件一网打尽

“Java全栈开发一网打尽&#xff1a;在Windows环境下探索技术世界的奇妙之旅” 前言 全栈开发是一项复杂而令人兴奋的任务&#xff0c;涵盖了从前端到后端、数据库到可视化层、消息队列到文件存储的广泛领域。本文将带您深入探讨在Windows环境下进行全栈开发的过程&#xff0…

CRM中的销售机会管理是什么?三个步骤帮你创建销售渠道

企业销售业务中&#xff0c;有个名词叫做“机会管理”&#xff0c;有效的机会管理可以帮助销售人员准确地抓住潜在客户群体&#xff0c;并将其转化为真正的客户、持续带来收入。CRM客户管理系统也是销售机会管理的一个重要工具&#xff0c;帮助销售人员与正确的人建立起关系&am…

Spring基础(2):放弃XML,走向注解

上一篇并没有实际地带大家去看源码&#xff0c;而是介绍了两个概念&#xff1a; BeanDefinitionBeanPostProcessor 当然&#xff0c;我介绍得非常笼统&#xff0c;不论是BeanDefinition还是BeanPostProcessor其实都有着较为复杂的继承体系&#xff0c;种类也很多。作为Spring…

王道考研--》顺序表课后习题C语言代码实现(冲刺)

考研是许多计算机科学专业学生追求高学历、寻求更好就业前景的途径。在考研过程中&#xff0c;数据结构是一个非常重要的科目&#xff0c;而代码实现题更是其中的难点之一。在这篇文章中&#xff0c;我们将探讨如何通过实现数据结构代码问题来提升考研成绩。无论您是否有编程经…

pytoch安装指定版本教程pytorch1.3安装笔记

一、先生成一个环境 如果电脑里安装了其他的torch版本&#xff0c;另外生成一个环境可以防止原先torch版本被替换掉。 打开conda的终端窗口输入以下命令就可以生成一个名为torch_1.3的环境&#xff1a; conda create -n torch_1.3 python3.6 输入以下命令进入到torch_1.3的…

vite基础学习笔记:13.Dialog 对话框 (用户注册与登录)

说明&#xff1a;自学做的笔记和记录&#xff0c;如有错误请指正 1. Dialog 对话框组件 目标效果&#xff1a;点击“登录/注册”&#xff0c;弹框 &#xff08;1&#xff09;创建全局组件&#xff0c;在官网中查询代码粘贴 &#xff08;2&#xff09; 注册和使用全局组件 &a…

NAT协议

目录 NAT 前言 NAT地址转换表 NAT分类 前言 静态NAT 192.168.1.2访问200.1.1.2执行过程 动态NAT 192.168.1.2访问200.1.1.2执行过程 NAPT 192.168.1.2的5000端口访问200.1.1.2的80端口执行过程 基本命令 配置动态NAPT转换 定义内外网接口 配置NAPT 静态NAPT配置…