.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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

APP备案明明是好事,为啥有些人反对呢?

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; APP和小程序备案&#xff0c; 这事在网上闹的沸沸扬扬&#xff0c;明明是好事&#xff0c;可为啥那么多人反对呢?而且最近出现了好多阴阳怪气的声音。 话说从2005年3月起&#xff0c;国内所有的网…

AI抢饭碗!多部由Midjourney+Runway,制作的电影火了!丨IDCF

ChatGPT等生成式AI正在重塑各个行业的工作模式&#xff0c;尤其是影视领域。最近&#xff0c;多部由MidjourneyRunway生成式AI制作的电影预告片在社交平台上火了。 一部名叫的《芭本海默》的电影从对白、场景、人物、切镜完全由生成式AI制作完成并受到了用户的好评。该片结合了…

IDEA简单拷贝一份新项目记录

IDEA简单拷贝项目记录 拷贝后改项目名&#xff0c;然后iml 配置文件改项目名&#xff0c;然后 .idea 中的compiler.xml 里面的name标签改项目名。 就可以了

3D Web轻量化引擎HOOPS Communicator如何实现对BIM桌面端的支持?

HOOPS Communicator是一款简单而强大的工业级高性能3D Web轻量化渲染开发包&#xff0c;其主要应用于Web领域&#xff0c;主要加载其专有的SCS、SC、SCZ格式文件&#xff1b;HOOPS还拥有另一个桌面端开发包HOOPS Visualize&#xff0c;主要加载HSF、HMF轻量化格式文件。两者虽然…

PyTorch深度学习实战(10)——过拟合及其解决方法

PyTorch深度学习实战&#xff08;10&#xff09;——过拟合及其解决方法 0. 前言1. 过拟合基本概念2. 添加 Dropout 解决过拟合3. 使用正则化解决过拟合3.1 L1 正则化3.2 L2 正则化 4. 学习率衰减小结系列链接 0. 前言 过拟合 (Overfitting) 是指在机器学习中&#xff0c;模型…

putty使用记录

在官网下载并安装putty 一、SSH 二、FTP open 192.168.1.118 put -r C:\Users\Administrator\Desktop\test /opt/lanren312/test # 上传&#xff08;文件夹&#xff09; get -r /opt/lanren312/test C:\Users\Administrator\Desktop\test2 # 下载&#xff08;文件夹&#xff…

边缘计算框架 Baetyl v2.4.3 正式发布

导读Baetyl v2.4.3 版本已经发布&#xff0c;对 v2.3.0 版本的部分功能进行了升级优化。公告称&#xff0c;这些新功能继续遵循云原生理念&#xff0c;构建了一个开放、安全、可扩展、可控制的智能边缘计算平台。 Baetyl 项目由百度发起&#xff0c;基于百度天工 AIoT 智能边缘…

【问题解决】Git命令行常见error及其解决方法

以下是我一段时间没有使用xshell&#xff0c;然后用git命令行遇到的一些系列错误和他们的解决方法 遇到了这个报错&#xff1a; fatal: Not a git repository (or any of the parent directories): .git 我查阅一些博客和资料&#xff0c;可以解决的方式&#xff1a; git in…

jQuery基础

目录 基础语法 选择器 层次选择器 属性选择器 基本过滤选择器 可见性过滤选择器 官网下载地址 两种包区别&#xff1a; $(document).ready()与window.onload类似&#xff0c;但也有区别。 基础语法 $(selector).action() 选择器 同html选择器等。 基本选择器包括标签选择器…

竞赛项目 深度学习的智能中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

后端人员如何快速上手vue

一、环境搭建 了解更多vue-cli 官网地址:https://cli.vuejs.org/zh/guide/browser-compatibility.html 前提 1.安装node(js代码的运行环境)、npm、cnpm/yarn&#xff1b; nodejs官网&#xff1a;https://nodejs.org/en cnpm安装&#xff1a;https://www.python100.com/htm…

uniapp 微信小程序 订阅消息

第一步&#xff0c;需要先去小程序官方挑选一下订阅模板拿到模板id 订阅按钮在头部导航上&#xff0c;所以 <u-navbar :bgColor"bgColor"><view class"u-nav-slot" slot"left" click"goSubscribe"><image :src"g…

leetcode59. 螺旋矩阵 II

题目&#xff1a;leetcode59. 螺旋矩阵 II 描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 思路&#xff1a; 代码&#xff1a; public class Solution {public int[][…

[C#] 简单的俄罗斯方块实现

一个控制台俄罗斯方块游戏的简单实现. 已在 github.com/SlimeNull/Tetris 开源. 思路 很简单, 一个二维数组存储当前游戏的方块地图, 用 bool 即可, true 表示当前块被填充, false 表示没有. 然后, 抽一个 “形状” 类, 形状表示当前玩家正在操作的一个形状, 例如方块, 直线…

弹簧滑块模型微分方程PLC数值求解(Euler和Runge-Kutta法SCL源代码)

龙格库塔法求解微分方程的PLC算法,还可以参看下面这篇文章博客: 微分方程数值解法(Runge-Kutta法PLC实现)_RXXW_Dor的博客-CSDN博客微分方程数值解法之欧拉法请参看下面的博客文章:微分方程数值解法(PID仿真用一阶被控对象库PLC算法实现)_数学微积分算法plc编程实例_RXXW_D…

液体神经网络:LNN是个啥概念?

一、说明 在在人工智能领域&#xff0c;神经网络已被证明是解决复杂问题的非常强大的工具。多年来&#xff0c;研究人员不断寻求创新方法来提高其性能并扩展其能力。其中一种方法是液体神经网络&#xff08;LNN&#xff09;的概念&#xff0c;这是一个利用动态计算功能的迷人框…

系统架构设计高级技能 · 系统质量属性与架构评估(二)【系统架构设计师】

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…

nginx负载均衡

nginx负载均衡 负载均衡&#xff1a;主要是由反向代理来实现的。 nginx的七层代理和四层代理 七层是最常见的反向代理方式&#xff0c;只能配置在nginx配置文件的http模块。而且upstream模块&#xff0c;不能写在server中&#xff0c;也不能在location中&#xff0c;在http模…

腾讯云轻量应用服务器端口怎么打开?图文方法来了

腾讯云轻量应用服务器端口放行在哪设置&#xff1f;在防火墙中可以开启端口号&#xff0c;腾讯云轻量应用服务器端口怎么开通&#xff1f;在轻量服务器管理控制台的防火墙中开启端口&#xff0c;如果是CVM云服务器在安全组中开通&#xff0c;腾讯云服务器网以轻量应用服务器开通…

(6)将Mission Planner连接到Autopilot

文章目录 前言 6.1 设置连接 6.2 故障处理 6.3 复合连接的故障处理 6.4 相关话题 前言 本文解释了如何将 Mission Planner 连接到自动驾驶仪上&#xff0c;以便接收遥测数据并控制飞行器。 &#xff01;Note 对于已有 ArduPilot 固件的安装&#xff0c;或没有现有 Ardu…