.netcore grpc的proto文件字段详解

news/2024/5/20 0:07:48 标签: .netcore, rpc

一、.proto文件字段概述

  1. grpc的接口传输参数都是根据.proto文件约定的字段格式进行传输的
  2. grpc提供了多种类型字段;主要包括标量值类型(基础类型)、日期时间、可为null类型、字节、列表、字典、Any类型(任意类型)、Oneof等
  3. 字段严格规范,是一种强类型文件协议

二、案例介绍

  1. 标量值类型
  2. 日期时间
  3. 可为null类型
  4. 字节
  5. 列表
  6. 字典
  7. Any类型
  8. Oneof:一种语言特性,可以通过该特性进行对象切换处理;使用 oneof 指定可能返回 A对象或B对象 的响应消息

三、服务端定义

  1. 定义通用消息实体
  2. 根据不同的类型创建对应的案例实体
  3. 特殊的字段需要导入指定的包才能使用
  4. 定义引用字段的各个服务接口
  5. 内部实现逻辑,及打印展示相应的字段结果
// 1.提供公共的实体proto文件
// 2.服务引用对应的proto文件


// 通用消息文件datamessages.proto
syntax = "proto3";

option csharp_namespace = "GrpcProject";

package grpc.serviceing;

// 基础类型实体
message BaseConfig{
	string name = 1;
	double position = 2;
	float distance= 3 ;
	int32 age = 4;
	int64 timeSpanId = 5;
	uint32 uAge = 6;
	uint64 uTimeSpanId = 7;
	sint32 sAge = 8;
	sint64 sTimeSpanId = 9;
	bool flag = 10;
}


// 日期类型实体 需要导入 日期namespace
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

message DateConfig{
	int64 id = 1;
	google.protobuf.Timestamp dateTimestamp = 2;
	google.protobuf.Duration dateDuration = 3;
}


// 字节类型
message ByteConfig{
	int64 id = 1;
	bytes positionBytes = 2;
}


// 可为null类型 需要导入 null的namespace
import "google/protobuf/wrappers.proto";

message NullConfig{
	int64 id = 1;
	google.protobuf.BoolValue nullBool = 2;
	google.protobuf.DoubleValue nullDoubule = 3;
	google.protobuf.FloatValue nullFloat = 4;
	google.protobuf.Int32Value nullInt = 5;
	google.protobuf.Int64Value nullLong = 6;
	google.protobuf.UInt32Value nullUInt = 7;
	google.protobuf.StringValue nullString = 8;
	google.protobuf.BytesValue nullBytes = 9;
}

//  集合类型
message ListConfig{
	int64 id = 1;
	// 数组
	repeated string names = 2;
	repeated ListDetailConfig details = 3;
	// 字典
	map<int32,string> attributes = 4;
	map<int32,ListDetailConfig> dicDetail = 5;
}

message ListDetailConfig{
	string name = 1;
	int32 height = 2;
}


// 任意类型 需要导入对应的包
import "google/protobuf/any.proto";
message AnyConfig{
	int32 id = 1;
	google.protobuf.Any anyObject = 2;
}

// Oneof类型  编译器在生成消息类时处理 oneof 关键字。 使用 oneof 指定可能返回 A 或 B 或 C 的响应消息
message OneofConfig{
	oneof result{
		A oA = 1;
		B oB = 2;
		C oC = 3;
	}
}

message A{
	int32 id = 1;
}

message B{
	int32 id = 1;
}

message C{
	int32 id =1;
}
// 接口服务定义protofield.proto文件

syntax = "proto3";

import "google/protobuf/empty.proto";
import "Protos/datamessages.proto";

option csharp_namespace = "GrpcProject";

package grpc.serviceing;

service FieldRpc{
	// 基础字段处理
	rpc BaseConfigService(BaseConfig) returns (google.protobuf.Empty);
	// 日期字段处理
	rpc DateConfigService(DateConfig) returns (google.protobuf.Empty);
	// 字节处理
	rpc ByteConfigService(ByteConfig) returns (google.protobuf.Empty);
	// null字段处理
	rpc NullConfigService(NullConfig) returns (google.protobuf.Empty);
	// 集合类型字段处理
	rpc ListConfigService(ListConfig) returns (google.protobuf.Empty);
	// 任意类型字段处理
	rpc AnyConfigService(AnyConfig) returns (google.protobuf.Empty);
	// Oneof类型字段处理
	rpc OneofConfigService(OneofConfig) returns (google.protobuf.Empty);
}
// 服务实现类

    /// <summary>
    /// 字段处理服务
    /// </summary>
    public class ProtoFieldService : FieldRpc.FieldRpcBase
    {
        // 基础配置
        public override async Task<Empty> BaseConfigService(BaseConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------基础配置--------------------------\r\n");
            // 打印字段信息
            var properties = request.GetType().GetProperties();
            foreach (var property in properties)
            {
                var value = property.GetValue(request);

                await Console.Out.WriteLineAsync($"{property.Name}:{value}");
            }
            return new Empty();
        }

        // 日期配置
        public override async Task<Empty> DateConfigService(DateConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------日期配置--------------------------\r\n");
            // timspan
            var duration = request.DateDuration.ToTimeSpan();
            await Console.Out.WriteLineAsync($"{nameof(duration)}:{duration.TotalSeconds}");
            // datetime
            var time = request.DateTimestamp.ToDateTime();
            await Console.Out.WriteLineAsync($"{nameof(time)}:{time:yyyy-MM-dd HH:mm:ss}");

            return new Empty();
        }

        // 字节
        public override async Task<Empty> ByteConfigService(ByteConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------字节配置--------------------------\r\n");

            var bytes = request.PositionBytes.ToByteArray();
            var message = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
            await Console.Out.WriteLineAsync($"{nameof(message)}:{message}");

            return new Empty();
        }
        // null配置
        public override async Task<Empty> NullConfigService(NullConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------null配置--------------------------\r\n");
            // 打印字段信息
            var properties = request.GetType().GetProperties();
            foreach (var property in properties)
            {
                var value = property.GetValue(request);
                var printValue = value == null ? "返回null值" : value;
                await Console.Out.WriteLineAsync($"{property.Name}:{printValue}");
            }

            return new Empty();
        }

        // 集合
        public override async Task<Empty> ListConfigService(ListConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------集合配置--------------------------\r\n");

            var id = request.Id;
            await Console.Out.WriteLineAsync($"主键标识:{id}\r\n");

            // 转换数组array
            await Console.Out.WriteLineAsync($"打印names信息:");
            var names = request.Names.ToArray();
            foreach (var name in names)
            {
                await Console.Out.WriteLineAsync(name);
            }

            // 转换list
            await Console.Out.WriteLineAsync($"\r\n打印detailList信息:");
            var detailList = request.Details.ToList();
            foreach (var item in detailList)
            {
                await Console.Out.WriteLineAsync($"ListDetailConfig:{nameof(item.Name)}  {item.Name};{nameof(item.Height)}  {item.Height}。");
            }

            // 字典

            await Console.Out.WriteLineAsync($"\r\n打印一般字典信息:");
            var dicAttributes = request.Attributes.ToDictionary(t => t.Key, t => t.Value);
            foreach (var attr in dicAttributes)
            {
                await Console.Out.WriteLineAsync($"key:{attr.Key};value:{attr.Value}。");
            }

            await Console.Out.WriteLineAsync($"\r\n打印对象字典信息:");
            foreach (var item in request.DicDetail)
            {
                await Console.Out.WriteLineAsync($"key:{item.Key};value:{item.Value.Name} | {item.Value.Height}。");
            }


            return new Empty();
        }

        // Any
        public override async Task<Empty> AnyConfigService(AnyConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------Any配置--------------------------\r\n");

            var anyObject = request.AnyObject;

            // 检查是否是A对象
            if (anyObject.Is(A.Descriptor))
            {
                var a = anyObject.Unpack<A>();
                if (a is not null)
                {
                    await Console.Out.WriteLineAsync($"A对象:{a.Id}");
                }
            }
            else if (anyObject.Is(B.Descriptor))
            {
                var b = anyObject.Unpack<B>();
                if (b is not null)
                {
                    await Console.Out.WriteLineAsync($"B对象:{b.Id}");
                }
            }
            else if (anyObject.Is(C.Descriptor))
            {
                var c = anyObject.Unpack<C>();
                if (c is not null)
                {
                    await Console.Out.WriteLineAsync($"C对象:{c.Id}");
                }
            }
            else
            {
                await Console.Out.WriteLineAsync("Any未解析到任何对象");
            }


            return new Empty();
        }

        // oneof
        public override async Task<Empty> OneofConfigService(OneofConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------Oneof配置--------------------------\r\n");

            // 检测对应的对象是否有值
            switch (request.ResultCase)
            {
                case OneofConfig.ResultOneofCase.None:
                    await Console.Out.WriteLineAsync("未检测到任何对象");
                    break;
                case OneofConfig.ResultOneofCase.OA:
                    await Console.Out.WriteLineAsync($"对象OA存在值:{request.OA.Id}");
                    break;
                case OneofConfig.ResultOneofCase.OB:
                    await Console.Out.WriteLineAsync($"对象OB存在值:{request.OB.Id}");
                    break;
                case OneofConfig.ResultOneofCase.OC:
                    await Console.Out.WriteLineAsync($"对象OC存在值:{request.OC.Id}");
                    break;
                default:
                    break;
            }


            return new Empty();
        }

    }

三、客户端定义

  1. 引用proto文件,配置为客户端类型
  2. 根据编译生成的函数进行传参调用
  3. 创建WPF测试客户端
  4. 各个服务接口创建对应的按钮进行调用
  5. 执行过程中,服务端控制台会打印对应的消息

 

        // 基础
        private async void BtnBaseconfig_Click(object sender, RoutedEventArgs e)
        {
           await WpfFieldClient.Show(1);
            MessageBox();
        }


        // 日期
        private async void BtnDateconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(2);
            MessageBox();
        }

        // 字节
        private async void BtnByteconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(3);
            MessageBox();
        }

        // null
        private async void BtnNullconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(4);
            MessageBox();
        }

        // list
        private async void BtnListconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(5);
            MessageBox();
        }

        // any
        private async void BtnAnyconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(6);
            MessageBox();
        }

        // Oneof
        private async void BtnOneofconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(7);
            MessageBox();
        }

调用的类库:

    public class WpfFieldClient
    {
        /// <summary>
        /// 根据参数选择不同的方法执行
        /// </summary>
        /// <param name="k"></param>
        public static async Task Show(int k)
        {
            var channel = GrpcChannel.ForAddress("https://localhost:7188");

            var client = new GrpcProject.FieldRpc.FieldRpcClient(channel);
            // 基础
            BaseConfig config = new BaseConfig();
            config.Name = "张三";
            config.Position = 2.33D;
            config.Distance = 5.48F;
            config.Age = 10;
            config.TimeSpanId = 6538590027736100;
            config.SAge = 1921;
            config.STimeSpanId = 6538590027736130;
            config.Flag = true;
            // 日期
            DateConfig dateConfig = new DateConfig();
            dateConfig.Id = 179;
            dateConfig.DateDuration = Duration.FromTimeSpan(TimeSpan.FromSeconds(5));
            // 注意这里的时间是utc时间
            dateConfig.DateTimestamp = Timestamp.FromDateTime(DateTime.UtcNow);

            // 字节
            ByteConfig byteConfig = new ByteConfig();

            byteConfig.Id = 9854564654654;
            byteConfig.PositionBytes = ByteString.CopyFrom(Encoding.UTF8.GetBytes("庄这人的南的很"));

            // null
            NullConfig nullConfig = new NullConfig();
            nullConfig.Id = 1854564654654;
            nullConfig.NullBool = true;
            nullConfig.NullFloat = null;
            nullConfig.NullUInt = null;
            nullConfig.NullInt = 15;
            nullConfig.NullLong = 112345451234787;

            // ListConfig
            ListConfig listConfig = new ListConfig();
            var attributes = new Dictionary<int, string>
            {
                [1] = "one",
                [2] = "two",
                [3] = "three",
                [4] = "four",
                [5] = "five"
            };

            listConfig.Id = 123456456;
            listConfig.Attributes.Add(attributes);

            var dicDetail = new Dictionary<int, ListDetailConfig>
            {
                [1] = new ListDetailConfig { Height = 1, Name = "one" },
                [2] = new ListDetailConfig { Height = 2, Name = "two" },
                [3] = new ListDetailConfig { Height = 3, Name = "three" },
                [4] = new ListDetailConfig { Height = 4, Name = "four" },
                [5] = new ListDetailConfig { Height = 5, Name = "five" }
            };

            listConfig.DicDetail.Add(dicDetail);

            listConfig.Details.Add(new ListDetailConfig { Height = 8, Name = "Eight" });

            var detailConfigs = new List<ListDetailConfig>
            {
               new ListDetailConfig { Height=9,Name="nine"},
               new ListDetailConfig{ Height=10,Name="ten"}
            };

            listConfig.Details.Add(detailConfigs);

            // Any
            AnyConfig anyConfig = new AnyConfig();
            anyConfig.Id = 42564134;

            anyConfig.AnyObject = Any.Pack(new B { Id = 15 });

            // Oneof
            OneofConfig oneofConfig = new OneofConfig();
            oneofConfig.OA = new A { Id = 1 };
            //oneofConfig.OC = new C { Id = 2 };


            var emptyResult = k switch
            {
                1 => await client.BaseConfigServiceAsync(config),
                2 => await client.DateConfigServiceAsync(dateConfig),
                3 => await client.ByteConfigServiceAsync(byteConfig),
                4 => await client.NullConfigServiceAsync(nullConfig),
                5 => await client.ListConfigServiceAsync(listConfig),
                6 => await client.AnyConfigServiceAsync(anyConfig),
                7 => await client.OneofConfigServiceAsync(oneofConfig),
                _ => new Empty()
            };
        }
    }

五、执行结果

服务端:

 

 客户端:

 六、源码地址

链接:https://pan.baidu.com/s/150TKY2Kgln3l_uKAsztyzw 
提取码:hkb9


http://www.niftyadmin.cn/n/4944380.html

相关文章

ansible 修改远程主机nginx配置文件

安装ansible brew install ansible 或者 pip3 install ansible 添加远程主机 设置秘钥 mac登录远程主机 ssh -p 5700 root192.168.123.211 ssh localhost #设置双机信任 ssh-kyegen -t rsa #设置主机两边的ssh配置文件 vi /etc/ssh/sshd_config/ PermitRootL…

通过shell监控域名ssl证书过期时间

#!/bin/bash source /etc/profile# 检测https证书有效期 # 设置过期前多少天提醒 remind_time30 # 设置监测域名&#xff0c;多个域名用英文逗号隔开[,] domains"www.test.com,www.baidu.com"domains_listecho $domains | awk -F, {print $0} | sed "s/,/ /g&qu…

神经网络基础-神经网络补充概念-40-神经网络权重的初始化

概念 神经网络权重的初始化是深度学习中的重要步骤&#xff0c;良好的权重初始化可以加速模型的训练收敛&#xff0c;提高模型的性能和稳定性。以下是一些常用的权重初始化方法&#xff1a; 零初始化&#xff08;Zero Initialization&#xff09;&#xff1a;将权重初始化为零…

SpringBoot集成Solr(一)保存数据到Solr

SpringBoot集成Solr&#xff08;一&#xff09;保存数据到Solr 添加依赖 <!--SpringBoot中封装过的Solr依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-solr</artifactId><ver…

LeetCode150道面试经典题-- 合并两个有序链表(简单)

1.题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 2.示例 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输…

Leetcode-每日一题【剑指 Offer 32 - I. 从上到下打印二叉树】

题目 从上到下打印出二叉树的每个节点&#xff0c;同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回&#xff1a; [3,9,20,15,7] 提示&#xff1a; 节点总数 < 1000 解题思路 1.题目要求我们从…

Gin路由组

Gin路由组 文章目录 Gin路由组接收任意请求的路由接收没有被定义的路由路由组完整代码 接收任意请求的路由 区别于以往的GET()函数只能处理一种请求,Any()函数可以处理各种函数 语法: func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc){} 案例: …

分布式 - 消息队列Kafka:Kafka 消费者的消费位移

文章目录 01. Kafka 分区位移02. Kafka 消费位移03. kafka 消费位移的作用04. Kafka 消费位移的提交05. kafka 消费位移的存储位置06. Kafka 消费位移与消费者提交的位移07. kafka 消费位移的提交时机08. Kafka 维护消费状态跟踪的方法 01. Kafka 分区位移 对于Kafka中的分区而…