2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GrpcをC#で実装するには

Posted at

GrpcをC#で実装するには

必要なNuGetパッケージ
Google.Protobuf
→やれることは以下のURLを参照
https://kagasu.hatenablog.com/entry/2018/04/29/233407#1-NuGet%E3%81%8B%E3%82%89-GoogleProtobuf-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B
今回は作成したprotoファイルを使うことに使用

Grpc
→Grpcを使用するためのライブラリ

Grpc.Reflection
Grpc.Tools
→Grpcで使用するファイル等を自動生成してくれるライブラリ
ビルドを実行することで自動生成される

Grpc環境の作成については以下のURLを参照
https://qiita.com/muroon/items/4e12dde47b9e8b1e94d3

前準備が完了したら、Grpcの実装を行っていく。

1.protoファイルの作成
下記が書き方の一例

syntax = "proto3";

package Grpctst;

service GrpcTest{
    rpc TestRun (TestRequest) returns (TestResponse) {}
}

message TestRequest{
    string request = 1; 
}

message TestResponse {
    string response = 1;
}

上記のファイルの意味
syntax:決まり文句みたいなもの
package:対象のnamespaceみたいなもの
service サービス名:サービスの名前とメソッドの定義引数と戻りを定義できる。
message メッセージ名:引数や戻り値の情報を定義する箇所
        stringやintなどの型を定義する。
        1は割り当てているIDみたいなものである。
        複数記載することも可能。

2.protoファイルの作成が完了後は、クラスライブラリMicrosoft.NET.Sdkを作成する。
作成後はプロジェクトのソリューションの設定に以下を追加する。


3.追加後にビルドを実行する。
実行するとクラスファイルを自動生成してくれる。
Grpctst.cs
GrpctstGrpc.cs
が生成されていればOK(ファイル名はパッケージ名いよって異なる)
これでGrpc操作を行う環境設定については完了。

4.データ受信の方法
受信を行うために以下のファイルを作成する。
GrpcTestImpl.cs(protoファイルのメソッドを設定するクラス)
GrpcTestReceive.cs(Grpcとやりとりをするためのクラス)

GrpcTestImpl.cs

class GrpcTestImpl : GrpcTest.GrpcTestBase
{
public override Task TestRun(TestRequest request, ServerCallContext context)
{
return Task.FromResult(new TestResponse { Response = request.request });
}
}

上記はGrpcTest.GrpcTestBaseを継承しています。
GrpcTestBaseは自動生成されたGrpctstGrpc.csの中で実装されています。
TestRunメソッドをオーバーライドして処理を記載することができます。
今回はテストですので、受信してきたデータをreturnするだけの処理としています。

GrpcTestReceive.cs(ほとんど決まり文句)

public class GrpcTestReceive
{
  const int Port = 50051;
  
  public void Run()
  {
    Server server = new Server
    {
      Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
    };

  var grpcTest = GrpcTest
      .BindService(new GrpcTestImpl())
      .Intercept(new GrpcInterceptor());
  server.Services.Add(grpcTest);

  var reflectionService = ServerReflection
      .BindService(new ReflectionServiceImpl(GrpcTest.Descriptor))
      .Intercept(new GrpcInterceptor());
  server.Services.Add(reflectionService);

  server.Start();
}

public class GrpcInterceptor : Interceptor
{
  public override Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(
    IAsyncStreamReader<TRequest> requestStream
    , ServerCallContext context
    , ClientStreamingServerMethod<TRequest, TResponse> continuation
    )
  {
    return base.ClientStreamingServerHandler(requestStream, context, continuation);
  }

 public override Task DuplexStreamingServerHandler<TRequest, TResponse>(
    IAsyncStreamReader<TRequest> requestStream
    , IServerStreamWriter<TResponse> responseStream
    , ServerCallContext context
    , DuplexStreamingServerMethod<TRequest, TResponse> continuation
    )
  {
    return base.DuplexStreamingServerHandler(requestStream, responseStream, context, continuation);
  }

  public override Task ServerStreamingServerHandler<TRequest, TResponse>(
    TRequest request
    , IServerStreamWriter<TResponse> responseStream
    , ServerCallContext context
    , ServerStreamingServerMethod<TRequest, TResponse> continuation
    )
  {
    return base.ServerStreamingServerHandler(request, responseStream, context, continuation);
  }

  public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
    TRequest request
    , ServerCallContext context
    , UnaryServerMethod<TRequest, TResponse> continuation
    )
  {
    foreach (var header in context.RequestHeaders)
    {
      Console.WriteLine(header);
    }

    var tokenHeader = context.RequestHeaders.FirstOrDefault((entry) => entry.Key == "token");
    if (tokenHeader == null)
    {
      context.Status = new Status(StatusCode.Unauthenticated, "ヘッダーにトークン情報がありません.");
    }
    return base.UnaryServerHandler(request, context, continuation);
  }
}

5.各種クラスの設定が完了したら実装は完了です。
実装が完了したらテストを行ってみる。
テストを行うのに便利なcurlツールでgrpcurlというのがあるので、使用してみるといいかもしれません。
インストールから使い方については以下を参照。
https://qiita.com/yukina-ge/items/a84693f01f3f0edba482

grpccurlのコマンド一例
サービス一覧表示
grpcurl -plaintext localhost:50051 list

サービス内のメソッド一覧を表示
grpcurl -plaintext localhost:50051 list サービス一覧表示で取得した名称

サービス呼び出し
grpcurl -plaintext localhost:50051 サービス一覧表示で取得した名称/サービス内のメソッド名称

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?