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

2

3

I'm trying to run the xamarin forms sample from the Dot net conf 2019 keynote. I've hosted the grpc service and a .net core console application can get data from it without any issues. But when running the xamarin app, the ALPN negotiation(Client hello) happens with http 1.1 and therefore the grpc call fails. Source code available here

Error message: Grpc.Core.RpcException: Status(StatusCode=Internal, Detail="Bad gRPC response. Response protocol downgraded to HTTP/1.1."

Debugger reveals that the SocketsHttpHandler used underneath on xamarin does not have the code that support Http 2.

Questions:

  1. Apparently Xamarin supports Grpc and Http. Why does this fail? Given that my suspect is correct, so that the issue is because xamarin uses an old version of System.Net.Http.dll that doesn't support Http2.
  2. How to make sure Xamarin uses correct runtime assemblies that support Http2?
  3. If this works for someone, Can you please share the system configuration?

Configuration

Use shared runtime: true
Mono shared runtime version (as seen on android device): 10.1.0-18.
Visual studio 2019 on windows 10:
Xamarin.Android SDK 10.1.4.0 (d16-4/e44d1ae)
Xamarin.Android Reference Assemblies and MSBuild support.
Mono: fd9f379
Java.Interop: xamarin/java.interop/d16-4@c4e569f
Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-5@9f4ed4b

Things I tried:

  1. Switch to Managed HttpClient implementation /NativeMessageHandler from ModernHttpClient. Still fails with same error. (Because ALPN negotiation still uses same code?)
  2. Send a HttpRequestMessage with Version 2 on a new HttpClient. Still the underlying handler is the same. So it fails to negotiate Http2.
  3. Disable shared runtime. Didn't work.

On .net core console app HttpConnectionSettings used by the SocketsHttpHandler has http2 supporting code: HttpConnectionSettings used by the SocketsHttpHandler has http2 supporting code

But on xamarin it doesn't. AndroidClientHandler is selected, but t delegates to the SocketsHttpHandler. It's settings doesn't have the http2 support: Xamarin fails

Curren answered 23/2, 2020 at 8:30 Comment(2)
Did you ever try this on iOS?Synoptic
@Synoptic No I didn't try on iOS. Only android.Curren
E
5

I make it work your provided solution. Sorry i didnt cover exact details why your way didnt worked and this one worked. Also i couldn't test iOs version.

Server. I changed only port version. I used release version. Btw I am not sure how successfully you could run Http1AndHttp2 and same ip and port. I had issues on personal project.

Mobile Added Grpc.Core and Grpc.Core.Api nugets to both projects.

I am creating channel differently. Your solution version

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

My version changed to

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

This is not very secure version but could work for some time since http2 is already binary. Create and use secure way you need to sign certificate and use it in server and client. Good example is here

Also i recommend to reuse channels since it is expensive to create new. Http2 is good at keeping multiple clients on one stream. You could recreate clients which is cheap operation.


A little update from MS https://learn.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.

Expansible answered 23/2, 2020 at 14:3 Comment(6)
Thanks! Actually the Grpc.Core library works. This is because it is a .net wrapper for the core c++ grpc lib, and therefore it doesn't depend on the managed SocketsHttpHandler.Curren
However I'll keep this question open for a while so that someone may point why the Http2 connection doesn't work with the managed handler. In fact the native wrapper library seems to add more bytes and increased my apk size by more than 20 MB. Hopefully this can be reduced in the release configuration though.Curren
Regarding security, I'm securing it with a free certificate from LetsEncrypt.Curren
@KavindaGayashan , i wasn't able to make it work always DNS address can't be resolved. You experienced this?Couldst
@Couldst Sorry, I don't recall seeing a DNS issue.Curren
@KavindaGayashan hi will you be able to have some samples? can't really make it work.Couldst
D
1

I found solution for this problem. And Grpc doesn't support Xamarin, UWP and Unity, and must use gRPC-Web instead. Grpc-web

Supported Platforms of Grpc

Dialect answered 17/1, 2022 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.