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

Kav*_*han 3 android xamarin http2 grpc

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

错误消息:Grpc.Core.RpcException:状态(StatusCode=Internal,Detail=“gRPC 响应错误。响应协议降级为 HTTP/1.1。”

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

问题:

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

配置

使用共享运行时:true
Mono 共享运行时版本(如在 Android 设备上看到的):10.1.0-18。
Windows 10 上的 Visual studio 2019:
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. 从 ModernHttpClient 切换到托管 HttpClient 实现 /NativeMessageHandler。仍然失败并出现同样的错误。(因为ALPN协商仍然使用相同的代码?)
  2. 在新的 HttpClient 上发送版本 2 的 HttpRequestMessage。底层处理程序仍然是相同的。所以它无法协商Http2。
  3. 禁用共享运行时。没用。

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

但在 xamarin 上却没有。选择了 AndroidClientHandler,但将其委托给 SocketsHttpHandler。它的设置不支持 http2: Xamarin 失败

val*_*asm 5

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

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

Mobile向这两个项目 添加了Grpc.CoreGrpc.Core.Api nuget。

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

var channel = GrpcChannel.ForAddress("123.123.123.123:123456");
Run Code Online (Sandbox Code Playgroud)

我的版本改为

var channel = new Channel("123.123.123.123:123456", ChannelCredentials.Insecure);
Run Code Online (Sandbox Code Playgroud)

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

我还建议重复使用频道,因为创建新频道的成本很高。Http2 擅长在一个流上保持多个客户端。您可以重新创建客户端,这是一种廉价的操作。


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

Xamarin 目前不支持使用 Grpc.Net.Client 通过 HTTP/2 调用 gRPC。我们正在努力在未来的 Xamarin 版本中改进 HTTP/2 支持。Grpc.Core 和 gRPC-Web 是当今可行的替代方案。