logo MSJO.kr

gRPC, SSL/TLS and C#

2019-10-05
MsJ
   

gRPC는 모든 환경에서 실행할 수 있도록 Google이 만든 최신 오픈소스 RPC 프레임워크이다. 대부분 언어와 플랫폼을 지원한다. 무엇보다 경량이며 Protobuf binary serialization 통해 네트워크 사용량을 감소하도록 한다. WCF(XML WebServices), WebAPI를 사용해 본 개발자라면 더 쉽게 접근할 수 있다. 기본적으로 gRPC는 구조화된 데이터를 직렬화하기 위해 Protocol Buffers를 사용한다. 확장자가 ‘.proto’인 일반텍스트 파일에 name-value 행태의 논리적 레코드를 작성한다.

사용법은 Intro to gRPC in C# - How To Get Started 동영상 강좌를 보거나 Microsoft의 gRPC 소개 문서를 참고한다. 이번 글에서는 사용법보다는 리눅스 서버와 윈도우 클라이언트로 개발할 때 SSL/TLS 이슈를 정리하였다. 기본 예제가 ‘https’로 대부분 되어있는데 ‘http’로 서버를 설정하고 콘솔 클라이언트에서 데이트를 호출하였다. 아래 소스는 Visual Studio 2019, .NET Core 3.0 - gRPC 프로젝트에서 기본 생성한 예제를 그대로 사용하였다.

서버: launchSettings.json
{
  "profiles": {
    "GrpcServer": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "http://0.0.0.0:5000;https://0.0.0.0:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
클라이언트: Program.cs
using Grpc.Core;
using GrpcServer;
using System;
using System.Threading.Tasks;

namespace GrpcConsole
{
    class Program
    {
        static async Task Main()
        {
            Channel channel = new Channel("192.168.1.29:5000", ChannelCredentials.Insecure);
            var client = new Greeter.GreeterClient(channel);
            string user = "가나닭";
            var reply = await client.SayHelloAsync(new HelloRequest { Name = user });
            Console.WriteLine("Greeting: " + reply.Message);
            //channel.ShutdownAsync().Wait();
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    }
}
클라이언트: SSL사용
using Grpc.Net.Client;
using GrpcServer;
using System;
using System.Threading.Tasks;

namespace GrpcConsole
{
    class Program
    {
        static async Task Main()
        {
            // [1]... http
            // AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
            // var channel = GrpcChannel.ForAddress("http://192.168.1.29:5000"); 
            
            // [2]... https : ignore the invalid certificate
            // using var httpClientHandler = new HttpClientHandler
            // {
            //     ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
            // };
            // using var httpClient = new HttpClient(httpClientHandler);
            // using var channel = GrpcChannel.ForAddress("https://192.168.1.29:5001", new GrpcChannelOptions { HttpClient = httpClient });       
            
            // [3]...
            var channel = GrpcChannel.ForAddress("https://localhost:5001");
            var client = new Greeter.GreeterClient(channel);
            var replay = await client.SayHelloAsync(new HelloRequest { Name = "가나닭" });
            Console.WriteLine(replay.Message);
            Console.ReadLine();
        }
    }
}
추가 패키지(NuGet)
Reference

Prεv(Θld)   Nεxt(Nεw)
Content
Search     RSS Feed     BY-NC-ND