.netcore grpc客户端流方法详解

一、客户端流式处理概述

  1. 客户端流式处理方法在该方法没有接收消息的情况下启动。 requestStream 参数用于从客户端读取消息。 返回响应消息时,客户端流式处理调用完成。
  2. 客户端可以发送多个消息流到服务端,当所有客户端消息流发送结束,调用请求流完结方法,则标记客户端流消息推送结束,等待服务端执行完成。
  3. 等同于客户端发送批量消息,服务端统一处理。

二、案例介绍

  1. 接下来 会提供三个案例,用于大家理解
  2. 第一个客户端流的基础用法
  3. 第二个客户端流的优化版本
  4. 第三个客户端的文件流式传输

三、服务端配置(注意:grpc相关配置参考我之前的文章

// 1.提供公共的实体proto文件
// 2.服务引用对应的proto文件
// 3.定义三个客户流方法// 公共messages.proto文件
syntax = "proto3";option csharp_namespace = "GrpcProject";package grpc.serviceing;// 请求体
message ServerRequest{string name = 1;double height = 2;int32 age = 3;bool flag = 4;float x = 5;float y = 6;float z= 7;repeated string departments = 8;
}message ServerFileRequest{bytes fileBytes = 1;
}// 响应体
message ServerResponse{bool result = 1;
}// clientstream.proto 定义service方法
syntax = "proto3";import "google/protobuf/empty.proto";
import "Protos/messages.proto";option csharp_namespace = "GrpcProject";package grpc.serviceing;service ClientStreamRpc{// 基础客户端流处理rpc StreamingFromClient	(stream ServerRequest) returns (ServerResponse);// foreach 客户端流式处理 前提使用C#8 或者更高版本rpc StreamingClientForeach(stream ServerRequest) returns (ServerResponse);// 文件流传输rpc FileStreamFromClient(stream ServerFileRequest) returns (ServerResponse);
}

服务接口实现:

   /// <summary>/// 客户端流式处理/// </summary>public class ClientStreamService : ClientStreamRpc.ClientStreamRpcBase{/// <summary>/// 基础访问流模式/// </summary>/// <param name="requestStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task<ServerResponse> StreamingFromClient(IAsyncStreamReader<ServerRequest> requestStream, ServerCallContext context){while (await requestStream.MoveNext()){await Console.Out.WriteLineAsync("\r\n-------------------------激光射线------------------------------\r\n");ServerRequest request = requestStream.Current;await Handle(request);}return new ServerResponse();}/// <summary>/// foreach访问流模式/// </summary>/// <param name="requestStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task<ServerResponse> StreamingClientForeach(IAsyncStreamReader<ServerRequest> requestStream, ServerCallContext context){await foreach (var request in requestStream.ReadAllAsync()){await Console.Out.WriteLineAsync("\r\n-------------------------激光射线------------------------------\r\n");await Handle(request);}return new ServerResponse();}/// <summary>/// 读取文件流 组合成完整的文件。/// </summary>/// <param name="requestStream"></param>/// <param name="context"></param>/// <returns></returns>public override async Task<ServerResponse> FileStreamFromClient(IAsyncStreamReader<ServerFileRequest> requestStream, ServerCallContext context){ServerResponse serverResponse = new ServerResponse();serverResponse.Result = false;// 存储流MemoryStream ms = new();await foreach (var request in requestStream.ReadAllAsync()){ms.Write(request.FileBytes.Span);await Console.Out.WriteLineAsync($"记录字节大小:{ms.Length} bytes");}string filePath = Path.Combine(Directory.GetCurrentDirectory(), "log.txt");using FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);fileStream.Position = 0;await fileStream.WriteAsync(ms.ToArray());fileStream.Flush();fileStream.Close();serverResponse.Result = true;return serverResponse;}private async Task Handle(ServerRequest request){if (request != null){foreach (var prop in request.GetType().GetProperties()){if (prop.CanRead && prop.GetValue(request) is not null){await Console.Out.WriteLineAsync($"property  name:{prop.Name};value:{prop.GetValue(request)}");}}}}}

 await foreach (var request in requestStream.ReadAllAsync()) 版本是C#8及以上版本才支持,这个需要注意!

四、客户端配置

  1. 引用proto文件,配置为客户端类型
  2. 根据编译生成的函数进行传参调用
    public partial class ClientStreamForm : Form{private readonly string _url;public ClientStreamForm(IConfiguration configuration){InitializeComponent();_url = configuration.GetConnectionString("ConnectionString");}private async void button1_Click(object sender, EventArgs e){var channel = GrpcChannel.ForAddress(_url);var client = new ClientStreamRpc.ClientStreamRpcClient(channel);var streamingFromClient = client.StreamingFromClient();for (int i = 0; i < 3; i++){ServerRequest request = new();request.Age = i;request.X = new Random(30).Next(50);request.Y = new Random(60).Next(50);request.Z = new Random(90).Next(50);request.Flag = i % 2 == 0 ? true : false;request.Height = 12;request.Departments.Add($"{i}");await streamingFromClient.RequestStream.WriteAsync(request);}await streamingFromClient.RequestStream.CompleteAsync();}private async void btnGrpcOptimize_Click(object sender, EventArgs e){var channel = GrpcChannel.ForAddress(_url);var client = new ClientStreamRpc.ClientStreamRpcClient(channel);var streamingFromClient = client.StreamingClientForeach();var departments = new List<string>(){"one","two","three","four","five","six"};ServerRequest request = new();foreach (var department in departments){request.Age = new Random(20).Next(100);request.X = new Random(30).Next(50);request.Y = new Random(60).Next(50);request.Z = new Random(90).Next(50);request.Flag = false;request.Height = 12;request.Departments.Add(department);await streamingFromClient.RequestStream.WriteAsync(request);}await streamingFromClient.RequestStream.CompleteAsync();}private async void btnFile_Click(object sender, EventArgs e){var channel = GrpcChannel.ForAddress(_url);var client = new ClientStreamRpc.ClientStreamRpcClient(channel);var streamingFromClient = client.FileStreamFromClient();var strMessage = "伟大抗日战争的一周年纪念,七月七日,快要到了。全民族的力量团结起来,坚持抗战,坚持统一战线,同敌人作英勇的战争,快一年了。这个战争,在东方历史上是空前的,在世界历史上也将是伟大的,全世界人民都关心这个战争。身受战争灾难、为着自己民族的生存而奋斗的每一个中国人,无日不在渴望战争的胜利。然而战争的过程究竟会要怎么样?能胜利还是不能胜利?能速胜还是不能速胜?很多人都说持久战,但是为什么是持久战?怎样进行持久战?很多人都说最后胜利,但是为什么会有最后胜利?怎样争取最后胜利?这些问题,不是每个人都解决了的,甚至是大多数人至今没有解决的。于是失败主义的亡国论者跑出来向人们说:中国会亡,最后胜利不是中国的。某些性急的朋友们也跑出来向人们说:中国很快就能战胜,无需乎费大气力。这些议论究竟对不对呢?我们一向都说:这些议论是不对的。可是我们说的,还没有为大多数人所了解。一半因为我们的宣传解释工作还不够,一半也因为客观事变的发展还没有完全暴露其固有的性质,还没有将其面貌鲜明地摆在人们之前,使人们无从看出其整个的趋势和前途,因而无从决定自己的整套的方针和做法。现在好了,抗战十个月的经验,尽够击破毫无根据的亡国论,也尽够说服急性朋友们的速胜论了。在这种情形下,很多人要求做个总结性的解释。尤其是对持久战,有亡国论和速胜论的反对意见,也有空洞无物的了解。“卢沟桥事变以来,四万万人一齐努力,最后胜利是中国的。”这样一种公式,在广大的人们中流行着。这个公式是对的,但有加以充实的必要。抗日战争和统一战线之所以能够坚持,是由于许多的因素:全国党派,从共产党到国民党;全国人民,从工人农民到资产阶级;全国军队,从主力军到游击队;国际方面,从社会主义国家到各国爱好正义的人民;敌国方面,从某些国内反战的人民到前线反战的兵士。总而言之,所有这些因素,在我们的抗战中都尽了他们各种程度的努力。每一个有良心的人,都应向他们表示敬意。我们共产党人,同其他抗战党派和全国人民一道,唯一的方向,是努力团结一切力量,战胜万恶的日寇。今年七月一日,是中国共产党建立的十七周年纪念日。为了使每个共产党员在抗日战争中能够尽其更好和更大的努力,也有着重地研究持久战的必要。因此,我的讲演就来研究持久战。和持久战这个题目有关的问题,我都准备说到;但是不能一切都说到,因为一切的东西,不是在一个讲演中完全说得了的。";var spanLength = strMessage.Length / 10;for (int i = 0; i < 10; i++){var startIndex = spanLength * i;string spanMessage;if (i == 9){spanMessage = strMessage.Substring(startIndex);}else{spanMessage = strMessage.Substring(startIndex, spanLength - 1);}var strBytes = Encoding.UTF8.GetBytes(spanMessage);var byteString = ByteString.CopyFrom(strBytes, 0, strBytes.Length);await streamingFromClient.RequestStream.WriteAsync(new ServerFileRequest() { FileBytes = byteString });Task.Delay(1000).Wait();}await streamingFromClient.RequestStream.CompleteAsync();}}
  1. IConfiguration 接口在program类中进行注入,读取appsettings.json文件
  2. 调用接口查看执行结果
    1. 客户端流基础模式

         2.客户端流foreach模式

           3.文件流处理模式

     

五、源码地址

链接:https://pan.baidu.com/s/1PnLhysfGbVxC1ecpu7XReA 
提取码:l6w0

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

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

相关文章

libheif —— 2、编写苹果、小米的.heic图片查看器

效果图 .heic简介 HEIC&#xff0c;是iOS 11更新后&#xff0c;iPhone 7及其后硬件&#xff0c;在拍摄照片时的默认图像存储格式。 HEIC是一种图像格式&#xff0c;上线时间还比较短&#xff0c;只有4年左右。自iOS 11和macOS High Sierra&#xff08;10.13&#xff09;内测开始…

16-2_Qt 5.9 C++开发指南_使用样式表Qss自定义界面

进行本篇介绍学习前&#xff0c;请先参考链接01_1_Qt工程实践_Qt样式表Qss&#xff0c;后再结合本篇进行融合学习如何使用样式表定义界面。 文章目录 1. Qt样式表2. Qt样式表句法2.1 一般句法格式2.2 选择器 (selector)2.3 子控件&#xff08;sub-controls&#xff09;2.4 伪状…

将应用设置成系统App/获取Android设备SN号

1&#xff0c;和系统签名一致&#xff1b;&#xff08;签名设置签名文件&#xff09; 2&#xff0c;配置Manifest 至此你的App就是一个系统App了&#xff0c;可以执行一些系统App才能有的操作&#xff0c;如获取机器SN号&#xff1a; public String getSerialNumber() {Strin…

lwip使用收发线程和不使用收发线程差异

使用收发线程的方式相对于不使用收发线程的方式&#xff0c;效率可能会稍低一些&#xff0c;这取决于具体的应用场景和实现方式。 lwIP&#xff08;轻量级IP协议栈&#xff09;是一个针对嵌入式系统的开源TCP/IP协议栈。它可以在单个线程中运行&#xff0c;也可以在多个线程中…

如何理解MySQL隔离性---3个记录隐藏字段、undo日志、Read View

目录 一、3个记录隐藏字段 二、undo 日志 三、read view 一、3个记录隐藏字段 本片文章是帮助理解上篇文章Mysql隔离性的辅助知识。 mysql在建表时&#xff0c;不仅仅创建了表的结构&#xff0c;还创建了3个隐藏字段。 DB_TRX_ID &#xff1a;6 byte&#xff0c;最近修改( 修…

梳理日常开发涉及的负载均衡

负载均衡是当前分布式微服务时代最能提及的词之一&#xff0c;出于对分层、解耦、弱依赖、可配置、可靠性等概念的解读&#xff0c;一对一的模式变得不再可信赖&#xff0c;千变万化的网络环境中&#xff0c;冗余和备份显得格外重要&#xff0c;稍大型的系统就会存在大量微服务…

MES系统在机器人行业生产管理种的运用

机器人的智能水平也伴随技术的迭代不断攀升。 2021年的春晚舞台上&#xff0c;来自全球领先工业机器人企业abb的全球首款双臂协作机器人yumi&#xff0c;轻松自如地表演了一出写“福”字&#xff0c;赢得了全国观众的赞叹。 在汽车装配领域&#xff0c;一台机器人可以自主完成一…

中级课程——XSS

文章目录 介绍挖掘思路分类反射型存储型dom类型 介绍 挖掘思路 注入点&#xff1a;各种输入框 测试代码&#xff08;poc&#xff09;&#xff1a;js语句 分类 反射型 存储型 dom类型

Wisej.NET Crack,Wisej.NET的核心功能

Wisej.NET Crack&#xff0c;Wisej.NET的核心功能 Wisej.NET是一个跨平台的web框架&#xff0c;用于使用.NET和C#/VB.NET而不是HTML和JavaScript构建现代HTML5应用程序。它包含创建任务关键型web应用程序所需的一切&#xff0c;包括UI组件、会话处理、状态管理和后端集成。借助…

go-admin 使用开发

在项目中使用redis 作为数据缓存&#xff1a;首先引入该包 “github.com/go-redis/redis/v8” client : redis.NewClient(&redis.Options{Addr: config.QueueConfig.Redis.Addr, // Redis 服务器地址Password: config.QueueConfig.Redis.Password, // Redis 密码&…

如何使用Mac终端给树莓派pico构建C/C++程序进行开发,以及遇到各种问题该怎么处理,不使用任何IDE或编辑器(例如VS Code)

写本文的原因是官方的教程已经过时了&#xff0c;如果你现在按照官方教程来在 Mac 上进行配置&#xff0c;那么会遇到一堆问题&#xff0c;比如我几乎把能踩的“雷”都踩了。所以这里记录了完整过程&#xff0c;以及各种错误的原因和处理方法&#xff0c;不然以后换 Mac 了或者…

Jenkins自动化打包脚本

一、背景 jenkins可以设置定时任务打包&#xff0c;也已手动点按钮打包&#xff0c;还可以通过执行http请求打包&#xff0c;今天我们就通过shell脚本&#xff0c;通过curl命令进行jenkins打包。 二、步骤 2.1 在jenkins上构建项目 设置触发器 2.2 通过shell脚本触发远程构…