--- lang: ja-jp breaks: true --- # gRPC を `.NET Framework` で使用する 2021-09-29 > .NET Standard 2.0 での gRPC クライアントの使用 > 次の .NET 実装 (またはそれ以降) では Grpc.Net.Client をサポートしていますが、HTTP/2 の完全サポートは提供していません。 > > https://docs.microsoft.com/ja-jp/aspnet/core/grpc/netstandard?view=aspnetcore-5.0#net-framework > .NET Framework では gRPC over HTTP/2 を制限付きでサポートしています。 .NET Framework で gRPC over HTTP/2 を有効にするには、WinHttpHandler を使用するようにチャネルを構成してください。 ## .NET client for gRPC (`Grpc.Net.Client`)は、`.NET Framework` にも利用可能 https://www.nuget.org/packages/Grpc.Net.Client `.NET Standard` と記載があるため、`.NET Framework` でも利用可能。 ![](https://i.imgur.com/6fA1p4R.png) ## 「gRPCは、HTTP/2上のgRPCをサポートしていない」とエラーが発生 ```shell= System.PlatformNotSupportedException: 'gRPC requires extra configuration on .NET implementations that don't support gRPC over HTTP/2. An HTTP provider must be specified using GrpcChannelOptions.HttpHandler.The configured HTTP provider must either support HTTP/2 or be configured to use gRPC-Web. See https://aka.ms/aspnet/grpc/netstandard for details.' ``` > HttpHandler の構成 > https://docs.microsoft.com/ja-jp/aspnet/core/grpc/netstandard#httphandler-configuration > HTTP プロバイダーは GrpcChannelOptions.HttpHandler を使用して構成する必要があります。 ハンドラーが構成されていない場合、エラーがスローされます。 > UWP、Xamarin、Unity など、HTTP/2 をサポートしていない .NET 実装では、代わりに gRPC-Web を使用できます。 > .NET gRPC クライアントを使用して gRPC-Web を構成する > https://docs.microsoft.com/ja-jp/aspnet/core/grpc/browser#configure-grpc-web-with-the-net-grpc-client ### チャネル作成処理を変更 .NET Framework では gRPC over HTTP/2 を制限付きでサポートしています。 .NET Framework で gRPC over HTTP/2 を有効にするには、`WinHttpHandler` を使用するようにチャネルを構成します。 :::info ASP.NET Coreサーバ側には、変更点はありません。クライアント側のみの変更となります。 ::: `System.Net.Http.WinHttpHandler`パッケージを追加 ```xml= <ItemGroup> <PackageReference Include="System.Net.Http.WinHttpHandler" Version="6.0.0-rc.1.21451.13" /> </ItemGroup> ``` ```csharp= string url = "https://localhost:5001"; var webhandler = new WinHttpHandler(); GrpcChannel channel = GrpcChannel.ForAddress(url, new GrpcChannelOptions { HttpHandler = webhandler }); ``` :::info UWP、Xamarin、Unity など、HTTP/2 をサポートしていない .NET 実装では、gRPC-Web を使用します。 ::: `Grpc.Net.Client.Web`パッケージを追加 ```xml= <ItemGroup> <PackageReference Include="Grpc.Net.Client.Web" Version="2.39.0" /> </ItemGroup> ``` ```csharp= using Grpc.Net.Client.Web; GrpcChannel channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = new GrpcWebHandler(new HttpClientHandler()) }); ``` ## `WinHttpHandler` を使用した場合に、`ウィンドウズ及びパッケージバージョンの要件が必要になる`とエラーになる。 ```shell= Grpc.Core.RpcException: 'Status(StatusCode="Cancelled", Detail="No grpc-status found on response. Using gRPC with WinHttp has Windows and package version requirements. See https://aka.ms/aspnet/grpc/netstandard for details.")' ``` 今使用しているWindows10のバージョンでは動作しない模様。。 :::info 注意 .NET Framework のサポートは初期段階で、プレリリースのソフトウェアを使用する必要があります。 * Windows 10 ビルド **19622** 以降は Windows Insider ビルドとして利用できます。 * System.Net.Http.WinHttpHandler バージョン 6.0.0-preview.3.21201.4 以降。 ::: ![](https://i.imgur.com/klMHKBA.png) ### Windows 11 にアップデートすると正常に動作した ![](https://i.imgur.com/FBr8EqD.png) ## `GrpcWebHandler` 使用した場合、 `HTTP/1.0 および HTTP/1.1 バージョンの要求のみが現在サポートされています。`とエラーが発生する。 ```shell= Grpc.Core.RpcException: 'Status(StatusCode="Internal", Detail="Error starting gRPC call. ArgumentException: HTTP/1.0 および HTTP/1.1 バージョンの要求のみが現在サポートされています。 パラメーター名:value", DebugException="System.ArgumentException: HTTP/1.0 および HTTP/1.1 バージョンの要求のみが現在サポートされています。 パラメーター名:value 場所 System.Net.HttpWebRequest.set_ProtocolVersion(Version value) 場所 System.Net.Http.HttpClientHandler.CreateAndPrepareWebRequest(HttpRequestMessage request) 場所 System.Net.Http.HttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) --- 直前に例外がスローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 場所 Grpc.Net.Client.Web.GrpcWebHandler.<SendAsyncCore>d__18.MoveNext() --- 直前に例外がスローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 場所 Grpc.Net.Client.Internal.GrpcCall`2.<RunCall>d__70.MoveNext()")' ``` 以下のようにして、`HttpVersion = new Version("1.1")`を指定すると、サーバ側でエラーとなる。 ```csharp= var webhandler = new GrpcWebHandler(new HttpClientHandler()); webhandler.HttpVersion = new Version("1.1"); GrpcChannel channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = webhandler } ``` ```shell= dbug: Microsoft.AspNetCore.Server.Kestrel[39] Connection id "0HMC324QVD9L0" accepted. dbug: Microsoft.AspNetCore.Server.Kestrel[1] Connection id "0HMC324QVD9L0" started. dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[3] Connection "0HMC324QVD9L0" established using the following protocol: Tls12 fail: Microsoft.AspNetCore.Server.Kestrel[0] HTTP/2 over TLS was not negotiated on an HTTP/2-only endpoint. dbug: Microsoft.AspNetCore.Server.Kestrel[2] Connection id "0HMC324QVD9L0" stopped. dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7] Connection id "0HMC324QVD9L0" sending FIN because: "The Socket transport's send loop completed gracefully." ``` ## `CallInvoker.AsyncDuplexStreamingCall` を使用して双方向通信を使用とすると、サーバ側で `HTTP/2 over TLS was not negotiated on an HTTP/2-only endpoint.` とエラーが発生する。 > .Net Core3.0 HTTP/2 over TLS was not negotiated on an HTTP/2-only endpoint #19707 > https://github.com/grpc/grpc/issues/19707 > .NET Standard 2.0 での gRPC クライアントの使用 > .NET Framework > **単項およびサーバー ストリーミングの gRPC 呼び出しのみがサポートされています。** つまり、`CallInvoker.AsyncDuplexStreamingCall`はサポートされていない。。。。 ###### tags: `gRPC` `.NET Framework` `Grpc.Net.Client` `WinHttpHandler` `GrpcWebHandler` `Windows 11`