.Net Framwork与.Net core进行gRPC通信

很少写博客,文笔也不太好,难免会存在各种问题,但是我希望能够给这个平台做一点儿个人的分享,本篇文章协作来源于实际项目需求,我国内互联网中未找到能实现的案例及处理解决方案;但是通过翻阅Stackoverflow,有了解决的办法,故此也分享给需要的程序员。

准备工作,使用的vs版本是2019,其中服务端平台是.Net Core,客户端是.Net Framwork

 一、服务端项目:创建Asp.net core grpc项目,如图:

 找到目标模板,然后选择项目存储位置后,直接下一步,默认框架版本是.net core 3.1版本,然后完成创建。

        项目结构:,我们可以看到模板中自动为我们创建了后缀.proto协议文件和GreeterService.cs类文件,这为我们省了很多事情,所以我们可以直接进入客户端了。

二、客户端项目创建及配置:

       1.、在vs2019中创建.Net Standard(.Net framwork)控制台,创建完成后,复制服务端的"greet.proto"协议文件到客户端,同时配置客户端控制台项目的.csproj文件,加入如下代码:

<ItemGroup>
    <Protobuf Include="greet.proto" GrpcServices="Client" />
  </ItemGroup>

         2、注意,文件名称和文件存放位置,如:存放在上一级目录,就可以Includ="xx\xxx.proto";

        3、安装相应的Nuget管理包:Grpc.Tools,Google.Protobuf,以及Grpc.Net.Client或者(Grpc.core,这个包目前进入维护,但是不提供更新了,微软和Grpc团队合作开发了Grpc.Net.Client),然后重新编译生成项目,进入客户端代码编写。

        4.客户端代码:注意这里代码,引用的插件是:Grpc.Net.Client,

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
            var reply = await client.SayHelloAsync(new HelloRequest { Name = "三鲜" });

            Console.WriteLine("来自" + reply.Message);

            channel.ShutdownAsync().Wait();
            Console.WriteLine("任意键退出...");
            Console.ReadKey();

5.联调,先启动服务端项目,后启动客户端项目,看效果,如图:

大概的意思是,因为服务端.net core 是http2,那么客户端需要配置http2请求,或者是用grpc-web发送请求,于是,开始增加grpc-web的Nuget包,重新测试,依旧是报错。

6、尝试了修改客户端,设置http2,以及服务端监听5001端口,如下代码,依旧是没用。

//客户端
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
//服务端,在启动类,Program中CreateHostBuilder函数中增加端口监听
webBuilder.ConfigureKestrel(options =>
                    {
                        options.AddServerHeader = false;
                        options.Listen(IPAddress.Loopback, 5001, listenOptions =>
                        {
                            //dlistenOptions.UseHttps(certificates);
                            listenOptions.Protocols = HttpProtocols.Http2;
                        });
                    });

7、其它尝试:https://docs.microsoft.com/zh-cn/aspnet/core/grpc/netstandard?view=aspnetcore-5.0,告诉我的理由是System.Net.Http.WinHttpHandler和win10版本不够。

8、使用自定义证书,打通成功,具体客户端代码和服务端代码:

//客户端
//server.pem 通过pwoershell创建的证书,然后通过openssl生成.pem文件
SslCredentials secureCredentials = new SslCredentials(File.ReadAllText("server.pem"));
            var channel = new Channel("localhost", 5001, secureCredentials);
            Console.WriteLine("链接完成");

            var client = new Greeter.GreeterClient(channel);
            Console.WriteLine("连接服务器");
            var reply = await client.SayHelloAsync(new HelloRequest { Name = "三鲜" });

            Console.WriteLine("来自" + reply.Message);

            channel.ShutdownAsync().Wait();
            Console.WriteLine("任意键退出...");
            Console.ReadKey();
//服务端:启动类,Program类中Main函数
public static void Main(string[] args)
        {
            //加载证书配置文件,
            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddEnvironmentVariables()
                .AddJsonFile("Certificate.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"certificate.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",optional:true,reloadOnChange:true)
                .Build();
            //读取配置文件中的节点下内容
            var certificateSettings = config.GetSection("certificateSettings");
            string certificateFileName = certificateSettings.GetValue<string>("fileName");
            string certificatePassword = certificateSettings.GetValue<string>("password");
            //提取私钥,验证客户端的请求,确保是安全的,可靠的请求
            var certificates = new X509Certificate2(certificateFileName, certificatePassword);

            var host = new WebHostBuilder().UseKestrel(options =>
            {
                options.AddServerHeader = false;
                options.Listen(IPAddress.Loopback, 5001, listenOptions =>
                  {
                      //这里很重要,它监控着5001端口的请求是否是安全的,携带公钥的
                      listenOptions.UseHttps(certificates);
                      listenOptions.Protocols = HttpProtocols.Http2;
                  });
            })
            .UseConfiguration(config)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .UseUrls("http://localhost:5001")
            .Build();
            host.Run();
            //CreateHostBuilder(args).Build().Run();
        }

补充,服务端需要增加证书源文件和证书配置.json,如图:

Certificate.json配置

pwoershell生成证书,源代码:

//中文的地方改成你的需要的
//生成后的证书位置c:\tmp
# setup certificate properties including the commonName (DNSName) property for Chrome 58+
$certificate = New-SelfSignedCertificate `
     -Subject 改成自己想要的标题不要带乱七八糟的符号(安装证书的时候会显示这个)`
     -DnsName 友好域名(例如:localhost) `
     -KeyAlgorithm RSA `
     -KeyLength 2048 `
     -NotBefore (Get-Date) `
     -NotAfter (Get-Date).AddYears(2) `
     -CertStoreLocation  "cert:CurrentUser\My"  `
     -FriendlyName  "证书的友好名称,在IIS指定的时候显示Certificate for .NET Core(Localhost Certificate for .Net Core)"  `
     -HashAlgorithm SHA256 `
     -KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment `
     -TextExtension @( "2.5.29.37={text}1.3.6.1.5.5.7.3.1" )
$certificatePath = 'Cert:\CurrentUser\My\' + ($certificate.ThumbPrint) 
 
# create temporary certificate path
$tmpPath =  "C:\tmp"
If(!(test-path $tmpPath))
{
New-Item -ItemType Directory -Force -Path $tmpPath
}
 
# set certificate password here
$pfxPassword = ConvertTo-SecureString -String  "你的证书的密码"  -Force -AsPlainText
$pfxFilePath =  "c:\tmp\你的证书的名称.pfx"
$cerFilePath =  "c:\tmp\你的证书的名称.cer"
 
# create pfx certificate
Export-PfxCertificate -Cert $certificatePath -FilePath $pfxFilePath -Password $pfxPassword
Export-Certificate -Cert $certificatePath -FilePath $cerFilePath
 
# import the pfx certificate
Import-PfxCertificate -FilePath $pfxFilePath Cert:\LocalMachine\My -Password $pfxPassword -Exportable
 
# trust the certificate by importing the pfx certificate into your trusted root
Import-Certificate -FilePath $cerFilePath -CertStoreLocation Cert:\CurrentUser\Root
 
# optionally delete the physical certificates (don’t delete the pfx file as you need to copy this to your app directory)
# Remove-Item $pfxFilePath
Remove-Item $cerFilePath

 9、重新编译服务端和客户端的代码,先运行服务端,然后再运行客户端,题外话:第一次不知道为什么,服务端有接受到请求,但是客户端并没有收到返回,于是决定第二天尝试,后来想想可能是openssl窗口影响了,第二天尝试,就成功了,如图:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值