C#コンソールアプリによるgRPC通信のサンプルコード

C#によるgRPC通信のサンプルコードに戻る

まず、最も簡単な gRPCサービスのサンプルを解説する。

gRPCサービスのサンプル

具体的なサンプルコードのプロジェクトファイルは以下のGitHUBリポジトリから公開しています。
(注意:2024年1月15日更新->.NET5.0はサポート終了しました。サンプルコードは.NET8.0に更新しました)

Release v1.7.1.0 · motoi-tsushima/Sample_GrpcService
.NET 8.0 により、リビルドしました。

IDEは、Visual Studio 2022 を使用する。

.NET のバージョンは、.NET6.0 を使用する。

Visual Studio 2022 を起動して、「新しいプロジェクトの作成」を開き、フィルターを「C#」「すべてのプラットフォーム」「サービス」で絞り込んで、「gRPCサービス」を選択して開く。

プロジェクト名、場所、ソリューション名などは任意で名付けます。

Visual Studio 2022 は gRPCサービスに必要なソースコードを自動作成します。

よって最小減必要なサンプルコードなら、特別にコードを書き足す必要はない。

自動生成されたコードは SayHello というAPIを実装している。

SayHello は、クライアントから HelloRequest型クラスのプロパティの Name に文字列値を渡して呼び出すと、返り値に HelloReply型クラスを返し、そのプロパティの Message にgRPCサービスから渡された文字列値を取得するAPIです。

SayHello の定義は「Proros」フォルダーの「greet.proto」ファイルの中で定義されている。

SayHello の実装は、「Services」フォルダーの「GreeterService.cs」ファイルの中で定義されている。

[greet.proto]ファイル

syntax = "proto3";

option csharp_namespace = "Sample_GrpcService";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

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

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

[GreeterService.cs]ファイル

using Grpc.Core;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sample_GrpcService
{
    public class GreeterService : Greeter.GreeterBase
    {
        private readonly ILogger<GreeterService> _logger;
        public GreeterService(ILogger<GreeterService> logger)
        {
            _logger = logger;
        }

        public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
        {
            return Task.FromResult(new HelloReply
            {
                Message = "Hello " + request.Name
            });
        }
    }
}

もし、新規のAPIを作成する場合は、この二つのファイルに新規APIの定義と実装コードを書き加える事になる。

今回は新規APIは書かないで SayHello をクライアント側から呼び出し、結果を表示するだけとする。

「greet.proto」ファイルは、APIの引数などインターフェイスの仕様を定義するもので、クライアント側と同じものを双方が保有する。

後でクライアント側のソースコードを用意するとき、この「greet.proto」ファイルをコピーして、クライアント側にも同じ「greet.proto」ファイルを持たせる。

これにより、gRPCサービスとクライアント側のアプリが、同じAPI仕様で通信する事ができる。

要するに「greet.proto」ファイルは通信データのシリアライズ仕様を定めたものだ。

もう一つ、知っておく必要のあるソースとして、「プロジェクトファイル内の Protobuf の定義がある。

プロジェクトの画面右上にある「ソリューションエクスプローラー」の該当プロジェクトをダブルクリックするとプロジェクトファイルのソースコードが表示される。

[プロジェクトファイルのソースコード]

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Protobuf Include="Protosgreet.proto" GrpcServices="Server" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Grpc.AspNetCore" Version="2.27.0" />
  </ItemGroup>

</Project>

このソースコードの ItemGroup ダグの中で Protobuf タグが定義されている。

この Protobuf タグが「greet.proto」ファイルを参照する事を定義している。

Include プロパティが「greet.proto」ファイルの場所を示し、GrpcServices プロパティがサーバー側である事を示している。

クライアント側のソースコードを作成する時は、クライアント側のプロジェクトにもこの定義を書き込む必要がある。

GrpcServices プロパティはクライアント側では「Client」になる。

実行方法

Visual Studio からビルドして実行してやるとコマンドプロンプトが起動する。

コマンドプロンプトはいくつかのメッセージを表示し、起動したままになっている。

この状態で gRPCサービスが起動した状態になっており、クライアントから SayHello APIを呼び出すと、結果を返せる状態になっている。

コマンドプロンプトにはデフォルトURLとして

「Now listening on: https://localhost:5001」と表示されているはずだ。

クライアントからはこのURLを呼び出す事になる。

ちなみに、 gRPCサービスを止める時は、コマンドプロンプトに「CTL + C」キーを入力すると止まる。

二回押すと停まり、任意のキーを押すとコマンドプロンプトが終了する。

クライアント側のgRPCコンソールアプリ

上記の最も簡単な gRPCサービスと通信するコンソールアプリのサンプルコードを解説する。

こちらも .NET のバージョンは、.NET6.0 を使用する。

具体的なサンプルコードのプロジェクトファイルは以下のGitHUBリポジトリから公開しています。

Release v1.7.1.0 · motoi-tsushima/Sample_gRPC_ConsoleApp
.NET 8.0 により、リビルドしました。

Visual Studio 2022 を起動して、「新しいプロジェクトの作成」を開き、フィルターを「C#」「すべてのプラットフォーム」「コンソール」で絞り込んで、「コンソール(.NET)」を選択して開く。

プロジェクト名、場所、ソリューション名などは任意で名付けます。

NuGetパッケージのインストール

作成したプロジェクトの画面右上にある「ソリューションエクスプローラー」の該当プロジェクトを右クリックして、ポップアップメニューから「NuGetパッケージの管理」を選びNuGet画面を開く。

NuGet画面の「参照」タブを選び、Grpc.Net.Client を検索して、選択する。

選択すると右側に「インストール」ボタンが現われるので、クリックしてインストールする。

同じ要領で、「Google.Protobuf」と「Grpc.Tools」もインストールする。

「ソリューションエクスプローラー」の「依存関係」の下の「パッケージ」の下にインストールしたNuGetパッケージが登録されているはずだ。

Protobuf の定義を登録

gRPCサービスのプロジェクトから「Protosgreet.proto」ファイルをフォルダーごと、コンソールアプリのプロジェクトへコピーする。

二つのプロジェクトをVisual Studio二重起動で両方開き、「ソリューションエクスプローラー」から、フォルダーをコピー・ペーストできるはずだ。

「greet.proto」ファイルの編集

そしてコンソールアプリのプロジェクトから「greet.proto」ファイルを開き、「option csharp_namespace」の値をコンソールアプリの「namespace」の値に書き換える。

ちなみに「namespace」の値はコンソールアプリの「Program.cs」に書かれている。

(Program.cs は後で掲載する)

サンプルコードでは「Sample_gRPC_ConsoleApp」となっている。

[greet.proto]ファイル

syntax = "proto3";

option csharp_namespace = "Sample_gRPC_ConsoleApp";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

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

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

プロジェクトファイルの編集

次に「ソリューションエクスプローラー」からプロジェクトファイルをダブルクリックしてソースを開き、 ItemGroup ダグの中で Protobuf タグを定義する。

編集後のプロジェクトファイル

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

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

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.14.0" />
    <PackageReference Include="Grpc.Net.Client" Version="2.34.0" />
    <PackageReference Include="Grpc.Tools" Version="2.35.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

追加したのは以下のコードだ。

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

これが 「greet.proto」を参照する事と、それがクライアント用である事を定義している。

メイン処理の記述

「Program.cs」にgRPCサービスと通信するメイン処理を書き込む。

[Program.cs]ファイル

using System;
using Grpc.Net.Client;

namespace Sample_gRPC_ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var channel = GrpcChannel.ForAddress("https://localhost:5001");
            var client = new Greeter.GreeterClient(channel);

            var response = client.SayHello(new HelloRequest { Name = "Motoi.Tsushima" });

            Console.WriteLine("Greeting: " + response.Message);
        }
    }
}

「using Grpc.Net.Client;」を最初に追加してGrpcライブラリを参照できるようにする。

「var channel = GrpcChannel.ForAddress(“https://localhost:5001“);」で、

gRPCサービスとのセッションを確立し、

「var client = new Greeter.GreeterClient(channel);」で、

「greet.protp」ファイルで定義した「service Greeter」のインスタンスを作成する。

「var response = client.SayHello(new HelloRequest { Name = “Motoi.Tsushima” });」で、

SayHello API を呼び出し、返り値の response に HelloReply型で結果を取得する。

この時点で通信は完了している。

結果をコンソールに表示して終わる。

ビルドして実行する

ビルドする前に、gRPCサービスを実行しておく。

コンソールアプリをビルドして実行すると、ローカル開発用のSSLの暗号キーを作成する旨の確認画面が表示される。

これは「OK」して先に進む。

これは一度しか出てこない。

起動したクライアント側のコンソールには「Greeting: Hello Motoi.Tsushima」と表示されているはずだ。

環境によって、gRPCサービスへのアクセスが拒否されてしまう場合もある。

これは大半がSSLの認証設定ができていないのが原因である。

HTTPSのアドレスにアクセスするには、ASP.NET Core HTTPS 開発証明書を信頼する設定を実施する必要がある。ターミナルのコマンドラインで以下のコマンドを実行するとそれができる。

dotnet dev-certs https –trust

開発証明書はSDKと一緒にインストールされている。

開発証明書についての解説は以下のサイトで行われている。

Windows と macOS で ASP.NET Core HTTPS 開発証明書を信頼する

コンソールの出力内容は、ソースを変更してご自分の名前に変更して試して見て欲しい。

以上、コンソールアプリによるgRPCサービスとの通信処理の最も簡単な作り方でした。

C#によるgRPC通信のサンプルコードに戻る

タイトルとURLをコピーしました