为什么 Xamarin Android 无法发送 GRPC/Http2 请求?

Why does Xamarin Android fails to send GRPC/Http2 requests?

我正在尝试 运行 来自 Dot net conf 2019 keynote 的 xamarin 表单示例。我托管了 grpc 服务,.net 核心控制台应用程序可以毫无问题地从中获取数据。 但是当 运行 连接 xamarin 应用程序时,ALPN 协商(客户端问候)发生在 http 1.1 上,因此 grpc 调用失败。 Source code available here

错误消息:Grpc.Core.RpcException:状态(StatusCode=Internal,Detail="Bad gRPC response. Response protocol downgraded to HTTP/1.1."

调试器显示 xamarin 底层使用的 SocketsHttpHandler 没有支持 Http 2 的代码。

问题:

  1. 显然 Xamarin 支持 Grpc 和 Http。为什么会失败? 鉴于我的怀疑是正确的,所以问题是因为 xamarin 使用不支持 Http2 的旧版本 System.Net.Http.dll。
  2. 如何确保 Xamarin 使用正确的 运行 支持 Http2 的时间程序集?
  3. 如果这对某人有用,你能分享一下系统配置吗?

配置

使用共享运行时间:真
Mono 共享 运行 时间版本(在 android 设备上看到):10.1.0-18。
Visual studio 2019 年 windows 10:
Xamarin.Android SDK 10.1.4.0 (d16-4/e44d1ae)
Xamarin.Android 参考程序集和 MSBuild 支持。
单声道:fd9f379
Java.Interop: xamarin/java.interop/d16-4@c4e569f
Xamarin.Android 工具:xamarin/xamarin-android-tools/d16-5@9f4ed4b

我试过的东西:

  1. 切换到托管 HttpClient 实现 /NativeMessageHandler 来自 ModernHttpClient。仍然失败并出现相同的错误。 (因为 ALPN 谈判仍然使用相同的代码?)
  2. 在新的 HttpClient 上发送版本 2 的 HttpRequestMessage。仍然 底层处理程序是相同的。所以它无法协商 Http2。
  3. 禁用共享 运行时间。没用。

在 .net 核心控制台应用程序上,SocketsHttpHandler 使用的 HttpConnectionSettings 具有 http2 支持代码:

但在 xamarin 上却没有。 AndroidClientHandler 被选中,但 t 委托给 SocketsHttpHandler。它的设置不支持 http2:

我让它工作你提供的解决方案。抱歉,我没有详细说明为什么您的方法不起作用而这个方法起作用了。我也无法测试 iOs 版本。

服务器。我只更改了端口版本。我用的是发行版。顺便说一句,我不确定 运行 Http1AndHttp2 和相同的 ip 和端口有多成功。我在个人项目上遇到了问题。

手机 向两个项目添加了 Grpc.Core and Grpc.Core.Api nugets。

我正在以不同的方式创建频道。您的解决方案版本

var channel = GrpcChannel.ForAddress("123.123.123.123:123456");

我的版本改为

var channel = new Channel("123.123.123.123:123456", ChannelCredentials.Insecure);

这不是很安全的版本,但可以使用一段时间,因为 http2 已经是二进制的。创建和使用您需要签署证书并在服务器和客户端中使用它的安全方式。很好的例子是 here

我还建议重复使用频道,因为创建新频道的成本很高。 Http2 善于将多个客户端保持在一个流上。您可以重新创建成本低廉的客户端。


来自 MS 的一点更新 https://docs.microsoft.com/en-us/aspnet/core/grpc/client?view=aspnetcore-3.1

Calling gRPC over HTTP/2 with Grpc.Net.Client is currently not supported on Xamarin. We are working to improve HTTP/2 support in a future Xamarin release. Grpc.Core and gRPC-Web are viable alternatives that work today.

我找到了这个问题的解决方案。而且 Grpc 不支持 Xamarin、UWP 和 Unity, 并且必须改用 gRPC-Web。 Grpc-web

Supported Platforms of Grpc