おーみんブログ

C#, ASP.NET Core, Unityが大好きです。

gRPCのServer Streaming通信をC#で体験してみた。

はじめに

最近少しずつ名前を聞くようになってきたgRPCを学習してみました。

gRPCには4つの通信方法がありますが、今回はそのうちの1つであるServer Streaming通信をC#で体験してみようと思います。

gRPCについて

Unary通信を体験したときに引用した2記事がとても分かりやすかったです!

gRPCのUnary通信をC#で体験してみた。 - おーみんブログ

作るもの

今回作るものはコンソールアプリ(クライアント側)で2つの数値を指定してサーバへ送信後、サーバからそれらの四則演算結果をそれぞれ別々のレスポンスとして返してあげるという内容です。

protoファイル

まずはprotoファイルを作ります。

syntax = "proto3";

package calc;

service CalcManager {
  rpc CalcFourArithmeticOperations (CalcRequest) returns (stream CalcReply);
}

message CalcRequest {
  int32 value1 = 1;
  int32 value2 = 2;
}

message CalcReply {
  string message = 1;
  int32 resultValue = 2;
}

Serviceで定義しているメソッドの返却値にstreamと付けてあげるのがポイントです。

サーバ側の実装

protoファイルから自動生成されたコードの中に{Service名} + "Base"のクラスがあるので、そちらを継承してサービスの処理を作ります。

public sealed class CalcService : CalcManager.CalcManagerBase
{
    public override async Task CalcFourArithmeticOperations(CalcRequest request, IServerStreamWriter<CalcReply> responseStream, ServerCallContext context)
    {
        int number = 1;

        // メッセージ
        string operation = string.Empty;
        // 四則演算結果
        int answer = 0;

        for(var i = 1; i < 5; i++)
        {
            switch (number) 
            {
                case 1:
                    operation = "足し算";
                    answer = request.Value1 + request.Value2;
                    break;
                case 2:
                    operation = "引き算";
                    answer = request.Value1 - request.Value2;
                    break;
                case 3:
                    operation = "掛け算";
                    answer = request.Value1 * request.Value2;
                    break;
                case 4:
                    operation = "割り算";
                    answer = request.Value1 / request.Value2;
                    break;
            }

            var reply = new CalcReply { Message = $"{operation}の結果です。", ResultValue = answer };
            await responseStream.WriteAsync(reply);
            number++;
            await Task.Delay(TimeSpan.FromSeconds(1));
        }
    }
}

クライアント側の実装

using Calc;
using Grpc.Core;
using Grpc.Net.Client;

// サーバのURLを適宜変更する必要があります。
using var channel = GrpcChannel.ForAddress("https://localhost:7015");
var client = new CalcManager.CalcManagerClient(channel);

// 四則演算用の値を2つ用意する
var value1 = int.Parse(Console.ReadLine());
var value2 = int.Parse(Console.ReadLine());

Console.WriteLine("・・・サーバへ送信中・・・");

var reply = client.CalcFourArithmeticOperations(new CalcRequest { Value1 = value1, Value2 = value2 });

// レスポンスがある限りループ
while(await reply.ResponseStream.MoveNext())
{
    Console.WriteLine(reply.ResponseStream.Current.Message);
    Console.WriteLine(reply.ResponseStream.Current.ResultValue);
}

Console.WriteLine("Press any key to exit...");
Console.ReadKey();

実行してみる

サーバを立ち上げた状態でクライアントアプリ(コンソールアプリ)を実行し、任意の数値2つを入力すると以下のように四則演算結果が返却されることが確認できます。

24
3
・・・サーバへ送信中・・・
足し算の結果です。
27
引き算の結果です。
21
掛け算の結果です。
72
割り算の結果です。
8
Press any key to exit...

おわりに

以上、gRPCのServer Streaming通信をC#で体験してみたという内容でした。
最初は使いどころがイメージできなかったのですが、調べてみるとプッシュ通知等に利用できるとのことです。
(アプリへ接続後、コネクションがずっと続くようになり、サーバ側から何かしらの通知を送ることができるというイメージ)

補足

他の通信についても以下の記事で体験しているのでご興味があればぜひ!

gRPCのUnary通信をC#で体験してみた。 - おーみんブログ

gRPCのClient Streaming通信をC#で体験してみた。 - おーみんブログ

gRPCのBidirectional streaming通信をC#で体験してみた。 - おーみんブログ