当前位置: 代码网 > it编程>编程语言>C# > C#中使用gRPC通讯的示例详解

C#中使用gRPC通讯的示例详解

2024年05月28日 C# 我要评论
在c#中使用grpc通讯参考:c#封装grpc类库及调用简单实例包括:grpc文件的创建生成、服务端和客户端函数类库的封装、创建服务端和客户端调用测试。创建并生成grpc服务文件创建新项目控制台应用

在c#中使用grpc通讯

参考:c#封装grpc类库及调用简单实例

包括:grpc文件的创建生成、服务端和客户端函数类库的封装、创建服务端和客户端调用测试。

创建并生成grpc服务文件

  • 创建新项目控制台应用 , 项目名称(mgrpc)
  • 安装三个nuget包 google.protobuf , grpc.core , grpc.tools
  • 项目添加新建项,选择类,修改名称为link.proto,添加后把link.proto里面内容清空

定义protocol

添加代码。测试实例为服务端和客户端传输字符串消息,只定义了一个方法(客户端调用,服务端重写),传输内容包括请求字符串和回复字符串。此处可自行定义。

syntax = "proto3";//proto3 是 protocol buffers 的第三个版本

// 指定了生成的 c# 代码的命名空间为 linkservice。当使用 protobuf 编译器 (protoc) 将这个 .proto 文件转换为 c# 代码时,生成的类将位于 linkservice 命名空间中
option csharp_namespace = "linkservice";

//定义了一个名为 link 的 grpc 服务。在 grpc 中,服务是由一个或多个 rpc 方法组成的
service link
{
	//定义了一个 rpc 方法。这个方法名为 getmessage,它接受一个 mes 类型的消息作为参数,
	//并返回一个 mes 类型的消息。在 grpc 中,客户端可以调用这个方法,并发送一个 mes 消息给服务端,然后服务端会处理这个消息并返回一个 mes 消息给客户端。
	rpc getmessage(mes) returns (mes);
}

//定义了一个名为 mes 的消息类型。在 protobuf 中,消息是由一系列字段组成的,每个字段都有一个名称、一个类型和一个标识符。
message mes
{
    // 客户端发送
	// 定义了一个名为 strrequest 的字段,类型为 string,标识符为 1。这个标识符在消息内部是唯一的,并且一旦分配就不能更改,因为它被用于序列化和反序列化过程中的字段识别。
	string strrequest = 1;
	// 同样定义了一个名为 strreply 的字段,类型为 string,标识符为 2。(服务端回复)
	string strreply = 2;
}

设置link.proto

右键link.proto文件选择属性,生成操作选择如图:

生成cs文件代码

生成解决方案。在下图路径得到自动生成的两个类。

至此,获得grpc服务需要的三个文件:link.proto、link.cs、linkgrpc.cs。可以将这三个文件放在一个项目中直接使用,需要重写一下服务端方法、创建服务端和客户端的启动方法。但是如果不同的项目软件之间通讯需要各自如此开发。可以先封装成一个grpc类库供其他项目直接调用。

服务端和客户端类库的封装

  • 创建类库(.net framework)项目 , 项目名称(grpclink)
  • 项目添加现有项,上面获得的三个文件(link.cs , linkgrpc.cs)。安装nuget包:grpc.core和google.protobuf。
  • 创建两个类:linkfunc用于放此类库可用于外部引用调用的方法。linkserverfunc基于link.linkbase,用于重写在proto文件中定义的方法。

对于不同的项目,在客户端请求时,服务端要根据自身情况回复想回的内容,因此可以提供一个委托供外部自行开发回复函数。

在linkfunc类中定义如下:

public static func<string, string> replymes;

linkserverfunc

在linkserverfunc类重写getmessage方法如下

using grpc.core;
using linkservice;
using system.threading.tasks;
using static linkservice.link;

namespace grpclink
{
    /// <summary>
    /// 重写在proto文件中定义的方法
    /// </summary>
    public class linkserverfunc : linkbase
    {
        public override task<mes> getmessage(mes request,servercallcontext context)
        {
            mes mes = new mes();
            mes.strreply = linkfunc.replymes(request.strrequest);
            return task.fromresult(mes);
        }
    }
}

linkfunc

using grpc.core;
using linkservice;
using system;
using static linkservice.link;

namespace grpclink
{
    public class linkfunc
    {
        /// <summary>
        /// 用于服务端回复委托
        /// </summary>
        public static func<string,string> replymes;

        // 定义服务端和客户端
        public static server linkserver;
        public static linkclient linkclient;

        /// <summary>
        ///  服务端启动
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public static void linkserverstart(string host,int port)
        {
            linkserver = new server
            {
                services =
                    {
                        bindservice(new linkserverfunc())
                    },
                ports = { new serverport(host,port,servercredentials.insecure) }
            };
            linkserver.start();
        }

        /// <summary>
        ///  服务端关闭
        /// </summary>
        public static void linkserverclose()
        {
            linkserver?.shutdownasync().wait();
        }

        /// <summary>
        /// 客户端启动
        /// </summary>
        /// <param name="strip"></param>
        public static void linkclientstart(string strip)
        {
            channel prechannel = new channel(strip,channelcredentials.insecure);
            linkclient = new linkclient(prechannel);
        }

        /// <summary>
        /// 客户端发送消息函数
        /// </summary>
        /// <param name="strrequest"></param>
        /// <returns></returns>
        public static string sendmes(string strrequest)
        {
            mes mes = new mes();
            mes.strrequest = strrequest;
            var res = linkclient.getmessage(mes);
            return res.strreply;
        }
    }
}

生成引用库

生成解决方案。debug中可以得到项目的dll文件grpclink.dll,其他项目可以引用使用了。

创建服务端和客户端调用测试

  • 创建两个控制台(.net framework)项目 , 项目名称testcilent , testserver
  • 将上述grpclink.dll文件分别放入两个项目中,并添加dll引用。 如果没有则安装nuget包:grpc.core和google.protobuf(此次测试没有安装)

testserver服务端

using grpclink;
using system;
using system.threading;

namespace testserver
{
    /// <summary>
    /// 测试服务端
    /// </summary>
    internal class program
    {
        static void main(string[] args)
        {
            linkfunc.linkserverstart("127.0.0.1",9008);
            thread.sleep(500);
            linkfunc.replymes = replymes;
            console.readkey();
        }


        /// <summary>
        /// 接收到客户端信息后回复
        /// </summary>
        /// <param name="strrequest">客户端发送过来的内容</param>
        /// <returns></returns>
        public static string replymes(string strrequest)
        {
            console.writeline("接收到:" + strrequest);
            switch (strrequest)
            {
                case "1":
                return "server识别到1";
                case "2":
                return "server识别到2";
                case "测试":
                return "开始测试"; 
                case "连接服务端":
                return "true";
            }
            return "server未识别到指定参数";
        }
    }
}

testcilent客户端

using grpclink;
using system;
using system.threading;

namespace testcilent
{
    internal class program
    {
        static void main(string[] args)
        {
            thread.sleep(2000);
            linkfunc.linkclientstart("127.0.0.1:9008");
            console.writeline("连接服务端中");
            string conn = linkfunc.sendmes("连接服务端");

            if (conn.equals("true"))
            {
                console.writeline("连接服务端成功!");


                for (int i = 0 ; i < 10 ; i++)
                {
                    thread.sleep(1000);
                    console.writeline("输入测试内容..");
                    var line = console.readline();
                    var ret = linkfunc.sendmes(line);
                    //获取到服务端返回的值
                    console.writeline(ret);

                }
            }

            console.writeline("连接失败 , 即将退出");
            thread.sleep(2000);
        }
    }
}

测试图例

以上就是c#中使用grpc通讯的示例详解的详细内容,更多关于c# grpc通讯的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com