当前位置: 移动技术网 > IT编程>开发语言>.net > GRPC与.net core

GRPC与.net core

2019年07月07日  | 移动技术网IT编程  | 我要评论

行尸走肉第六季第二集,我们无处安放的青春txt,侯志慧

系列章节

grpc与.net core

grpc截止时间与元数据

grpc与netcore identity

grpc与netcore identityserver4

概述

grpc的数据交互模式有:

1.单项rpc,最简单的数据交换方式,客户端发出单个请求,收到单个响应

2.服务端流式rpc,是在服务端收到客户端的请求之后,返回一个应答流,客户端收到流之后处理。

3.客户端流式rpc,与单项类似,但客户端发送的是流式rpc

4.双向流式rpc,调用由客户端调用方法来初始化,而服务端则接收到客户端的元数据,方法名和截止时间。服务端可以选择发送回它的初始元数据或等待客户端发送请求。下一步怎样发展取决于应用,因为客户端和服务端能在任意顺序上读写 - 这些流的操作是完全独立的。例如服务端可以一直等直到它接收到所有客户端的消息才写应答,或者服务端和客户端可以像"乒乓球"一样:服务端后得到一个请求就回送一个应答,接着客户端根据应答来发送另一个请求,以此类推。

单项rpc较简单不做示例了。

首先在vs2019中net core3.0中新建grpc项目。然后定义响应的proto文件,根据proto文件生成响应的服务端与客户端代码。

1.服务端流式rpc

1.定义 protofile

syntax = "proto3";

option csharp_namespace = "grpcgreeter";

package greet;

// the greeting service definition.
service greeter {
  // sends a greeting
  rpc sayhello (hellorequest) returns (helloreply) {}
  rpc getstreamcontent (streamrequest) returns (stream streamcontent) {}
}

// the request message containing the user's name.
message hellorequest {
  string name = 1;
}

// the response message containing the greetings.
message helloreply {
  string message = 1;
}
message streamrequest {
  string filename = 1;
}
message streamcontent {
  bytes content = 1;
}

2.实现服务端service

重新生成项目,然后实现getstreamcontent,简单的读取文件内容,并将内容返回给client

using system;
using system.collections.generic;
using system.io;
using system.linq;
using system.threading.tasks;
using google.protobuf;
using grpc.core;

namespace grpcgreeter
{
    public class greeterservice : greeter.greeterbase
    {
        public override task<helloreply> sayhello(hellorequest request, servercallcontext context)
        {
            return task.fromresult(new helloreply
            {
                message = "hello " + request.name
            });
        }

        public override task getstreamcontent(streamrequest request, iserverstreamwriter<streamcontent> responsestream, servercallcontext context)
        {
            return task.run(async () =>
             {
                 using (var fs = file.open(request.filename, filemode.open)) // 从 request 中读取文件名并打开文件流
                 {
                     var remaininglength = fs.length; // 剩余长度
                     var buff = new byte[1048576]; // 缓冲区,这里我们设置为 1 mb
                     while (remaininglength > 0) // 若未读完则继续读取
                     {
                         var len = await fs.readasync(buff); // 异步从文件中读取数据到缓冲区中
                         remaininglength -= len; // 剩余长度减去刚才实际读取的长度

                         // 向流中写入我们刚刚读取的数据
                         await responsestream.writeasync(new streamcontent
                         {
                             content = bytestring.copyfrom(buff, 0, len)
                         });
                     }
                 }
             });
        }
    }
}

 

3.实现client

新建一个netcore 3.0的console项目,并引入nuget包

install-package grpc.net.client -version 0.1.22-pre1
install-package google.protobuf -version 3.8.0
install-package grpc.tools -version 1.22.0

 

编辑项目文件,修改如下节点

<protobuf include="protos\greet.proto" grpcservices="client" />

 

重新生成项目,client端主要实现发送请求,请求是一个服务器端的文件路径。然后实现接收服务端的流,并保存到client本地。

using grpc.net.client;
using grpcgreeter;
using system;
using system.collections.generic;
using system.io;
using system.net.http;

namespace grpcgreeterclient
{
    class program
    {
        static async system.threading.tasks.task main(string[] args)
        {
            appcontext.setswitch(
                "system.net.http.socketshttphandler.http2unencryptedsupport",
                true);
            var httpclient = new httpclient();
            // the port number(50051) must match the port of the grpc server.
            httpclient.baseaddress = new uri("http://localhost:50051");
            var client = grpcclient.create<greeter.greeterclient>(httpclient);
            //
            var reply = await client.sayhelloasync(
                              new hellorequest { name = "greeterclient" });
            console.writeline("greeting: " + reply.message);
            console.readkey();

            //
            var result = client.getstreamcontent(new streamrequest { filename = @"d:\docs.zip" });  //发送请求
            var iter = result.responsestream;
            using (var fs = new filestream(@"d:\docs2.zip", filemode.create)) // 新建一个文件流用于存放我们获取到数据
            {
                while (await iter.movenext()) // 迭代
                {
                    iter.current.content.writeto(fs); // 将数据写入到文件流中
                }
            }

            console.readkey();
        }
    }
}

 

文件生成成功

 2.客户端流式rpc

1.定义 protofile

syntax = "proto3";

option csharp_namespace = "grpc.test";

package greet;

// the greeting service definition.
service greeter {
  rpc getresult (stream value) returns (result) {}
}


//定义value消息类型,用于客户端消息
message value {
    int32 value = 1;
}
//定义result消息类型,包含总和,数字数量和平均值,用于服务端消息返回
message result {
    int32 sum = 1;
    int32 cnt = 2;
    double avg = 3;
}

 

2.实现服务端service

重新生成项目,并实现如下

using system;
using system.collections.generic;
using system.io;
using system.linq;
using system.threading.tasks;
using google.protobuf;
using grpc.core;

namespace grpc.test
{
    public class greeterservice : greeter.greeterbase
    {
        public override async task<result> getresult(iasyncstreamreader<value> requeststream, servercallcontext context)
        {
            while (await requeststream.movenext())
            {
                var point = requeststream.current;
            }
            return new result { sum = 1 };
        }
    }
}

 

3.实现client

新建一个netcore 3.0的console项目,并引入nuget包,安装nuget包与其他操作同上一个例子,实现代码如下

using grpc.net.client;
using system;
using system.collections.generic;
using system.io;
using system.net.http;

namespace grpc.test.client
{
    class program
    {
        static async system.threading.tasks.task main(string[] args)
        {
            appcontext.setswitch(
                 "system.net.http.socketshttphandler.http2unencryptedsupport",
                 true);
            var httpclient = new httpclient();
            // the port number(50051) must match the port of the grpc server.
            httpclient.baseaddress = new uri("http://localhost:50051");
            var client = grpcclient.create<greeter.greeterclient>(httpclient);
            using (var call = client.getresult())
            {
                await call.requeststream.writeasync(new value { value_ = 1 });
                await call.requeststream.completeasync();
                var response = await call.responseasync;
            }

            console.readkey();
        }
    }
}

 

 3.双向流式rpc

1.定义proto

syntax = "proto3";

option csharp_namespace = "grpc.test";

package greet;

// the greeting service definition.
service greeter {
  rpc getresult (stream value) returns (stream result) {}
}


//定义value消息类型,用于客户端消息
message value {
    int32 value = 1;
}
//定义result消息类型,包含总和,数字数量和平均值,用于服务端消息返回
message result {
    int32 sum = 1;
    int32 cnt = 2;
    double avg = 3;
}

 

2.服务端实现

重新生成项目,并实现如下

public override async task getresult(iasyncstreamreader<value> requeststream, iserverstreamwriter<result> responsestream, servercallcontext context)
        {
            while (await requeststream.movenext())
            {
                var note = requeststream.current;

                await responsestream.writeasync(new result { sum = 100 });
            }
        }

 

3.客户端代码

新建一个netcore 3.0的console项目,并引入nuget包,安装nuget包与其他操作同上一个例子,实现代码如下

using grpc.net.client;
using system;
using system.collections.generic;
using system.io;
using system.net.http;
using system.threading.tasks;

namespace grpc.test.client
{
    class program
    {
        static async system.threading.tasks.task main(string[] args)
        {
            appcontext.setswitch(
       "system.net.http.socketshttphandler.http2unencryptedsupport",
       true);
            var httpclient = new httpclient();
            // the port number(50051) must match the port of the grpc server.
            httpclient.baseaddress = new uri("http://localhost:50051");
            var client = grpcclient.create<greeter.greeterclient>(httpclient);
            using (var call = client.getresult())
            {
                var responsereadertask = task.run(async () =>
                {
                    while (await call.responsestream.movenext())
                    {
                        var note = call.responsestream.current;
                        console.writeline("received " + note);
                    }
                });

                await call.requeststream.writeasync(new value { value_ = 12 });
                await call.requeststream.completeasync();
                await responsereadertask;
            }

            console.readkey();
        }
    }
}

 

至此,grpc的几种数据交互分享完毕

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网