WPF + gRPCでチャットサーバ・クライアントの実装

gRPCのお試し実装として、チャットサーバ・クライアントを作った。せっかくなのでヘキサゴナルアーキテクチャ

github.com

.protoファイルのサービス定義はこれ。すべてのRPCをクライアント側から要求するため、サービスはクライアント視点でのメソッドとして定義すると分かり易いだろう。

サービス定義

service Chat {
  rpc Write(ChatLog) returns (google.protobuf.Empty) {}
  rpc Subscribe(google.protobuf.Empty) returns (stream ChatLog) {}
}

なお、chat.csはProtobufGeneratorで生成している。(バージョン1.2でgRPC対応した)

cactuaroid.hatenablog.com

クライアント側の実装

ChatServiceClient.cs

streamの場合、IAsyncEnumerator<T>を渡されるが扱いにくいのでIAsyncEnumerable<T>に変換してから扱っている。拡張メソッドを用意した。


(2020/4/5追記)

gRPCのバージョンアップによりSystem.Interactive.Asyncへの依存が削除され、それに伴いIAsyncEnumerator<T>ではなくIAsyncStreamReader<T>が渡されるようになった。IAsyncEnumerable<T>へ変換してから扱った方が扱いやすいことには変わりなく、以下の拡張メソッドを用意した。

https://github.com/cactuaroid/GrpcWpfSample/blob/master/GrpcWpfSample.Client/Model/IAsyncStreamReaderExtensions.cs

サーバ側の実装

ChatServiceGrpcServer.cs

Subscribe()ではForEachAsync()で書き込みたかったので、IObservable<T>IAsyncEnumerable<T>に変換して扱っている。Ix-Async(IAsyncEnumerable<T>)を使うのかRx(IObservable<T>)を使うのかは適宜判断する。このサンプルではgRPCサーバ以外の箇所ではRxを使っている。

cactuaroid.hatenablog.com

あと簡単な認証の実験として、IPアドレスで接続可否を判断するようにした。テスト用なのでlocalhost=127.0.0.1のみ許可している。

IpAddressAuthentication.cs

参考:gRPC (C#) に追加されたインターセプターの使用方法|mxProject

参考

こちらのブログでかなり色々試されているので参考になる。

mxProject: gRPC