おーみんブログ

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

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

はじめに

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

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

gRPCについて

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

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

作るもの

今回作るものはコンソールアプリ(クライアント側)で4つの数値をそれぞれサーバへ送信後、サーバからそれらの平均値をレスポンスとして返してあげるという内容です。

protoファイル

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

syntax = "proto3";

package calc;

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

message CalcRequest {
  int32 value = 1;
}

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

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

サーバ側の実装

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

public sealed class CalcService : CalcManager.CalcManagerBase
{
    public override async Task<CalcReply> CalcAverage(IAsyncStreamReader<CalcRequest> requestStream, ServerCallContext context)
    {
        int count = 0;
        double result = 0.0;

        await foreach(var request in requestStream.ReadAllAsync())
        {
            // サーバへ値が届いているか確認
            Console.WriteLine($"{request.Value}を受け取りました。");

            result += request.Value;
            count++;
        }

        return new CalcReply() { Message = "計算完了しました", ResultValue = result / count };
    }
}

クライアント側の実装

using Calc;
using Grpc.Net.Client;

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

for(var i = 0; i < 4; i++)
{
    var value = int.Parse(Console.ReadLine());
    var request = new CalcRequest() { Value = value };

    await stream.RequestStream.WriteAsync(request);
}

// サーバへメッセージの送信が完了した旨を通知
await stream.RequestStream.CompleteAsync();

// サーバからのレスポンス
var response = await stream.ResponseAsync;
Console.WriteLine(response.Message);
Console.WriteLine($"平均値は{response.ResultValue}です。");

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

実行してみる

サーバを立ち上げた状態でクライアントアプリ(コンソールアプリ)を実行し、数値を4つ入力(送信)すると以下のように平均値が返却されることを確認できます。

2
4
6
8
計算完了しました
平均値は5です。
Press any key to exit...

今回はサーバ側が逐一値を受け取っていることも確認しているのでそちらのコンソールも見てみましょう。
クライアント側から値を送信する度に値を受け取っていることが分かります。

2を受け取りました。
4を受け取りました。
6を受け取りました。
8を受け取りました。

おわりに

以上、gRPCのClient Streaming通信をC#で体験してみたという内容でした。 こちらは主に重いファイルをアップロードする際などに少しずつ送信する、などの用途に用いられるみたいですね。

補足

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

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

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

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