.netcore grpc双向流方法详解
一、双向流处理概述
- 简单来讲客户端可以向服务端发送消息流,服务端也可以向客户端传输响应流,即客户端和服务端可以互相通讯
- 客户端无需发送消息即可开始双向流式处理调用 。 客户端可选择使用
RequestStream.WriteAsync发送消息。 使用ResponseStream.MoveNext()或ResponseStream.ReadAllAsync()可访问从服务流式处理的消息。ResponseStream没有更多消息时,双向流式处理调用完成。
二、案例简介
- 客户端发送请求流通过
equestStream.WriteAsync传入到服务端 - 服务端响应到客户端的流通过
ResponseStream.WriteAsync写入到客户端 - 服务端使用System.Threading.Channels保证线程安全交互
三、服务端配置(注意:grpc相关配置参考我之前的文章)
- 配置.proto文件
// 1.提供公共的实体proto文件
// 2.服务引用对应的proto文件
// 3.定义三个客户流方法//定义messages.proto文件令需要注意项目文件中的特性GrpcServices=None;syntax = "proto3";option csharp_namespace = "GrpcProject";package grpc.serviceing;// 消息推送/接收实体
message ExampleMessage
{string msg = 1;
}// 双向流文件twowaystream.protosyntax = "proto3";import "Protos/messages.proto";option csharp_namespace = "GrpcProject";package grpc.serviceing;service BothWaysRpc{// 双向流rpc StreamingBothWays(stream ExampleMessage) returns (stream ExampleMessage);
}
- 1 服务接口实现
/// <summary>/// 双向流服务/// </summary>public class BothWaysService : BothWaysRpc.BothWaysRpcBase{/// <summary>/// 自动重置事件/// </summary>private readonly ManualResetEventSlim _event;public BothWaysService(){_event = new ManualResetEventSlim(false);}public override async Task StreamingBothWays(IAsyncStreamReader<ExampleMessage> requestStream,IServerStreamWriter<ExampleMessage> responseStream,ServerCallContext context){// 创建线程安全的有限容量通道var channel = Channel.CreateBounded<ExampleMessage>(new BoundedChannelOptions(capacity: 5));var task = Task.Run(async () =>{await foreach (var message in requestStream.ReadAllAsync()){// 读取消息 写入通道if (!string.IsNullOrWhiteSpace(message.Msg)){await Console.Out.WriteLineAsync($"记录客户端传入消息:{message.Msg}");// todo 消息处理await channel.Writer.WriteAsync(message, context.CancellationToken);}}}, context.CancellationToken);await foreach (var message in channel.Reader.ReadAllAsync()){// 打印通道接收的消息await Console.Out.WriteLineAsync($"通道传入消息:{message.Msg}");// 写入响应流ExampleMessage exampleMessage = new ExampleMessage() { Msg = $"我已经接收到消息:{message.Msg}" };await responseStream.WriteAsync(exampleMessage);if (message.Msg.ToLower() == "exit"){break;}}// 完结写入通道channel.Writer.Complete();await task;}}
- 2 Program注入
public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);builder.Services.AddGrpc();var app = builder.Build();// 一元方法//app.MapGrpcService<DollarService>();// 客户端流//app.MapGrpcService<ClientStreamService>();// 服务端流//app.MapGrpcService<ServerStreamService>();// 双向流app.MapGrpcService<BothWaysService>();app.Run();}}
四、客户端配置
- 引用proto文件,配置为客户端类型
- 根据编译生成的函数进行传参调用
- 创建WPF测试客户端

button按钮触发grpc
/// <summary>/// BothWaysClient.xaml 的交互逻辑/// </summary>public partial class BothWaysClient : Window{public BothWaysClient(){InitializeComponent();}private async void Excute_Click(object sender, RoutedEventArgs e){Action<string> action = str => { txtValue.Text += $"{str}\r\n"; };await WpfClient.Show(action);txtValue.Text += "\r\n\r\n";}}
grpc客户端接口调用
/// <summary>/// 双向流/// </summary>/// <param name="action"></param>/// <returns></returns>public static async Task Show(Action<string> action){var messages = new List<string>(){"test","one","two","three","false","four","Oooo","dddd","vvvfff","exit"};Random rnd = new Random(20);var channel = GrpcChannel.ForAddress("https://localhost:7188");var client = new GrpcProject.BothWaysRpc.BothWaysRpcClient(channel);var bothWays = client.StreamingBothWays();var requestTask = Task.Run(async () =>{while (true){var index = rnd.Next(messages.Count);var msg = messages[index];await bothWays.RequestStream.WriteAsync(new ExampleMessage { Msg = msg });if (msg == "exit"){break;}}});await foreach (var item in bothWays.ResponseStream.ReadAllAsync()){action(item.Msg);if (item.Msg == "我已经接收到消息:exit"){break;}}await requestTask;}
五、执行结果
服务端:

客户端:

六、源码地址
链接:https://pan.baidu.com/s/1uCirfbexPJ7C-AujBVtkCQ
提取码:sd4y
七、后续进阶简介
- 接下来会讲解客户端工厂,优化客户端请求地址使用依赖注入提取各个服务
- proto文件各个字段详细介绍
- token认证
- 截止时间(中止请求)和请求取消
- AOP切面策略
- 重试策略(policy)
- 负载均衡策略(grpc本身提供的策略及nginx代理)
- 日志记录
- 健康检查
- 后续有更多特色功能会持续补充
相关文章:
.netcore grpc双向流方法详解
一、双向流处理概述 简单来讲客户端可以向服务端发送消息流,服务端也可以向客户端传输响应流,即客户端和服务端可以互相通讯客户端无需发送消息即可开始双向流式处理调用 。 客户端可选择使用 RequestStream.WriteAsync 发送消息。 使用 ResponseStream…...
【Servlet】(Servlet API HttpServlet 处理请求 HttpServletRequest 打印请求信息 前端给后端传参)
文章目录 Servlet APIHttpServlet处理请求 HttpServletRequest打印请求信息前端给后端传参 Servlet API Servlet中常用的API HttpServlet 实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service destory 服务器终止的时候会调用. //下面的注解把当前类和…...
java中右移>>和无符号右移>>>的区别
public static void main(String[] args) {byte[] dest new byte[2];dest[0] 0x15; //0001 0101dest[1] (byte) 0xfb;//1111 1011System.out.println((dest[0] >> 4) & 0xff);//右移 应该是0000 0001 十进制结果显示1 结果也是1,正确System.out.printl…...
牛客周赛 Round 7
目录 A 游游的you矩阵 题目: 题解: AC 代码: B 游游的01串操作 题目: 题解: AC 代码: C 游游的正整数 题目: 题解: AC 代码: D 游游的选数乘积 题目…...
R语言生存分析(机器学习)(1)——GBM(梯度提升机)
GBM是一种集成学习算法,它结合了多个弱学习器(通常是决策树)来构建一个强大的预测模型。GBM使用“Boosting”的技术来训练弱学习器,这种技术是一个迭代的过程,每一轮都会关注之前轮次中预测效果较差的样本,…...
k8s和docker简单介绍
当涉及到容器技术和容器编排时,Docker和Kubernetes是两个重要的概念。我将更详细地介绍它们以及它们之间的关系。 Docker: Docker是一种容器化技术,它允许你将应用程序及其依赖项打包到一个称为"容器"的封闭环境中。每个容器都包…...
Lua学习记录
Lua基础了解 Lua的注释通过 (-- 单行注释,--[[ ]] 多行注释)可以不加; 多个变量赋值,按顺序赋值,没有则为nil; function的简单用法,多个返回值配合多重赋值,以end为结束标志 Lua下标从1开始&…...
三分钟完美解决你的C盘内存过大爆红
一、清理回收站 二、清理桌面 建议一 不要在桌面放太多图标或者文件会占用过多的内存,可以放到其他盘建议二、 将位置移动到别的盘 三、手动删除下载文件与缓存文件 日常使用中会通过Windows下载各种文件资料到电脑中,它默认也是直接下载在C盘中的。如果我们在以…...
C++ - equal(比较两个vector元素)
C标准库的std::equal函数。这个函数用于比较两个范围的元素是否相等。 在使用std::equal函数时,您需要提供两个范围的迭代器,以及一个可选的谓词函数(predicate)。函数会比较第一个范围内的元素和第二个范围内的元素是否相等。如果…...
多线程:线程池
线程池 提前创建多个线程放入线程池中,使用时直接获取,使用完直接放入池中;可以避免频繁创建销毁,实现重复利用,类似生活中的公共交通工具。好处:提高相应速度;降低资源消耗;便于线…...
9.3.2.2网络原理(传输层TCP)
TCP全部细节参考RFC标准文档 一.TCP特点: 有连接,可靠传输,面向字节流,全双工. 二.TCP数据报: 1.端口号是传输层的重要概念. 2.TCP的报头是变长的(UDP是固定的8字节),大小存在4位首部长度中,用4个bit位(0~15)表示长度单位是4字节.(TCP报头最大长度是60字节,前面20字节是固定…...
ssm+mybatis无法给带有下划线属性赋值问题
原因:mybaitis根据配置,将有下划线的字段名改为了驼峰格式。 具体见:ssmmybatis无法给带有下划线属性赋值问题,无法获取数据库带下划线的字段值 - 开发者博客 解决方式: 直接将实体类中的下划线去掉返回值使用resul…...
学习笔记-JVM监控平台搭建
SpringBoot Actuator 1 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>2 开启配置 # 暴露所有的监控点【含Prometheus】 management.endpoin…...
使用css实现时间线布局(TimeLine)
前言 在使用uni-app开发微信小程序过程中,遇到了时间轴布局,由于每项的内容高度不一致,使用uniapp自带的扩展组件uni-steps,样式布局无法对齐竖线,于是自己造轮子,完成特殊的布局。显示效果如下࿱…...
深入浅出 栈和队列(附加循环队列、双端队列)
栈和队列 一、栈 概念与特性二、Stack 集合类及模拟实现1、Java集合中的 Stack2、Stack 模拟实现 三、栈、虚拟机栈、栈帧有什么区别?四、队列 概念与特性五、Queue集合类及模拟实现1、Queue的底层结构(1)顺序结构(2)链…...
前端基础(二)
前言:前端开发框架——Vue框架学习。 准备工作:添加Vue devtools扩展工具 具体可查看下面的这篇博客 添加vue devtools扩展工具添加后F12不显示Vue图标_MRJJ_9的博客-CSDN博客 Vue官方学习文档 Vue.js - 渐进式 JavaScript 框架 | Vue.js MVVM M…...
ORB-SLAM2学习笔记7之System主类和多线程
文章目录 0 引言1 整体框架1.1 整体流程 2 System主类2.1 成员函数2.2 成员变量 3 多线程3.1 ORB-SLAM2中的多线程3.2 加锁 0 引言 ORB-SLAM2是一种基于特征的视觉SLAM(Simultaneous Localization and Mapping)系统,它能够从单个、双目或RBG…...
gin的占位符:和通配符*
1、用法 在 Gin 路由中,可以使用一个通配符(*)或一个占位符(:)来捕获 URL 的一部分。 r.GET("/royal/:id", func(c *gin.Context) {id : c.Param("id")//fmt.Println("into :id")c.Str…...
【量化课程】08_2.深度学习量化策略基础实战
文章目录 1. 深度学习简介2. 常用深度学习模型架构2.1 LSTM 介绍2.2 LSTM在股票预测中的应用 3. 模块分类3.1 卷积层3.2 池化层3.3 全连接层3.4 Dropout层 4. 深度学习模型构建5. 策略实现 1. 深度学习简介 深度学习是模拟人脑进行分析学习的神经网络。 2. 常用深度学习模型架…...
12-数据结构-数组、矩阵、广义表
数组、矩阵、广义表 目录 数组、矩阵、广义表 一、数组 二.矩阵 三、广义表 一、数组 这一章节理解基本概念即可。数组要看清其实下标是多少,并且二维数组,存取数据,要先看清楚是按照行存还是按列存,按行则是正常一行一行的去读…...
实例】四相机测量项目源码使用海康SDK及C#+halcon实现的通俗易懂教程:连接相机、模板匹...
四相机测量项目源码,海康相机SDK,C#halcon,写得比较通俗易懂,四相机四种测量模式,某工厂产线曾使用的项目。 主要功能有连接海康相机采图,模板匹配,圆形拟合,直线拟合,像…...
春联生成模型-中文-base:3步生成专业级春节对联
春联生成模型-中文-base:3步生成专业级春节对联 1. 认识你的AI春联助手 春节将至,家家户户都开始准备贴春联。但创作一副既工整又富有寓意的春联并非易事。春联生成模型-中文-base正是为解决这一需求而生的AI工具。 这个模型基于阿里达摩院AliceMind团…...
3步搞定音乐标签混乱问题的终极解决方案
3步搞定音乐标签混乱问题的终极解决方案 【免费下载链接】music-tag-web 音乐标签编辑器,可编辑本地音乐文件的元数据(Editable local music file metadata.) 项目地址: https://gitcode.com/gh_mirrors/mu/music-tag-web 你是否曾为音…...
GHelper:华硕笔记本的轻量级控制中心 - 简单高效的硬件管理方案
GHelper:华硕笔记本的轻量级控制中心 - 简单高效的硬件管理方案 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, …...
新手避坑指南:用STLink-V2给STM32F103RCT6烧录程序,从CubeMX配置到Keil调试全流程
STM32开发实战:从CubeMX配置到Keil调试的完整避坑手册 第一次接触STM32开发时,那种既兴奋又忐忑的心情我至今记忆犹新。看着手边的STLink-V2调试器和STM32F103RCT6开发板,明明按照教程一步步操作,却总在某个环节卡住——驱动死活装…...
FastAPI中间件性能优化:从GZip压缩到异步日志的7个提速技巧
FastAPI中间件性能优化:从GZip压缩到异步日志的7个提速技巧 当你的FastAPI应用开始处理每秒数千甚至百万级的请求时,中间件可能成为性能瓶颈的隐形杀手。本文将揭示如何通过7个关键技巧,让你的中间件处理速度提升300%以上。 1. 理解中间件的性…...
如何用iTorrent在iPhone上轻松管理种子下载?iOS种子客户端全攻略
如何用iTorrent在iPhone上轻松管理种子下载?iOS种子客户端全攻略 【免费下载链接】iTorrent Torrent client for iOS 16 项目地址: https://gitcode.com/gh_mirrors/it/iTorrent iTorrent是一款专为iOS 16设备设计的开源种子客户端,让iPhone和iPa…...
如何绕过百度网盘限速?这个开源工具让你免费享受会员级下载速度
如何绕过百度网盘限速?这个开源工具让你免费享受会员级下载速度 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘的龟速下载而烦恼吗?每天…...
【LLMs篇】Qwen模型家族:从架构设计到多模态应用的全面解析
1. Qwen模型家族的技术架构演进 第一次接触Qwen模型时,最让我惊讶的是它在保持Transformer基础架构的同时,通过一系列精妙改进实现了性能突破。作为阿里云推出的开源大模型家族,Qwen从7B到72B参数规模的版本都采用了类似的架构设计理念&#…...
Cisco Unified Communications Manager (CallManager) 15 SU4a - 统一通信与协作
Cisco Unified Communications Manager (CallManager) 15 SU4a - 统一通信与协作 思科统一通信管理器 (CallManager) 请访问原文链接:https://sysin.org/blog/cisco-ucm-15/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 思…...
