Как заставить GrpcChannel использовать HTTP/2 на MonoAndroid?

Я пытаюсь выполнить запрос к моему серверу по MagicOnion (он использует транспорт от gRPC, но другой протокол сериализации, message pack вместо protobuf).

Небольшой тестовый клиент, запускающийся под net5.0 выполняет примерно такой код:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var address = $"http://{ServerUrl.Host}:5002";
using var channel = GrpcChannel.ForAddress(address);
var myServiceClient = MagicOnionClient.Create<IMyService>(channel);
var result = await myServiceClient.GetMyData();

...и успешно получает ответ. Однако когда я пытаюсь выполнить в точности такой-же код на Android, я вижу такую ошибку в логе сервера:

Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException: HTTP/2 connection error (PROTOCOL_ERROR): Invalid HTTP/2 connection preface.
    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ParsePreface(ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.TryReadPrefaceAsync()
    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ProcessRequestsAsync[TContext](IHttpApplication`1 application)

По логам и дампу трафика видно что клиент на .Net 5 использует HTTP/2, а на Android - HTTP/1.1. На сколько я могу понять, это единственная разница между двумя запросами.

Как сделать так, чтобы клиент на Android (API 30, monoandroid10) использовал всё же HTTP/2?


Ответы (1 шт):

Автор решения: bearpro

Решение состоит в том чтобы использовать другую библиотеку с реализацией GrpcChannel - Grpc.Core.
В моём случае она сразу не заработала, я получил ошибку связанную с загрузкой libgrpc_csharp_ext Чтобы она заработала в Xamarin, нужно так же подключить Grpc.Core.Xamarin той же версии, что и Grpc.Core. MagicOnionClient отлично работает с GrpcChannel из этой библиотеки.

Вот так выглядит рабочий пример:

var channel = new Grpc.Core.Channel(ServerUrl.Host, 5002, Grpc.Core.ChannelCredentials.Insecure);
var myServiceClient = MagicOnionClient.Create<IMyService>(channel);
var result = await myServiceClient.GetMyData();
→ Ссылка