Android HttpClient get SocketException (Connection reset by peer) after 2-3 minutes when sending larger files

Andreas Brosten 116 Reputation points
2021-11-09T21:16:58.02+00:00

I'm uploading files to azure blob storage with a normal HttpClient from my Xamarin forms project.
I set a timeout value of 10 minutes for the HttpClient.
Sending files (up to around 100MB) works perfect on iOS and UWP. On Android however, smaller files works great, but when trying to send 50-100MB large files, I get SocketException at the end of each send session. The exception is reproducable all the time, but depending on filesize and bandwidth, it comes after different amount of time. Usually 2-4 minutes.
So, the failing request is a call to httpClient.SendAsync(myRequest)
It's tested on three different Android devices and all behaves the same (different brands).
HttpClient implementation = Android
SSL/TLS implementation = Native TLS 1.2+

I guess something gets disposed too early, but seems out of my control. I am not doing any other http calls in the meantime.
Any idéas?

Stack track:
at System.Net.Http.HttpContent.CopyToAsyncCore (System.Threading.Tasks.ValueTask copyTask) [0x00089] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:375
at System.Net.Http.HttpConnection.SendRequestContentAsync (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpConnection+HttpContentWriteStream stream, System.Threading.CancellationToken cancellationToken) [0x00058] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs:796
at System.Net.Http.HttpConnection.SendAsyncCore (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x012e6] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs:748
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync (System.Net.Http.HttpConnection connection, System.Net.Http.HttpRequestMessage request, System.Boolean doRequestAuth, System.Threading.CancellationToken cancellationToken) [0x000e6] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs:330
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync (System.Net.Http.HttpRequestMessage request, System.Boolean doRequestAuth, System.Threading.CancellationToken cancellationToken) [0x00101] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs:296
at System.Net.Http.RedirectHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x00070] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs:32
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x000d7] in <6735d06e4e7e46e0b8693d25d7699ab4>:0
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x000ef] in <6735d06e4e7e46e0b8693d25d7699ab4>:0
at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) [0x0017e] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:506 at MyApp.Client.ApiClients.ApiClientBase.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancelToken) [0x00037] in C:\.....\MyApp.Client\ApiClients\ApiClientBase.cs:25 at MyApp.Client.Operations.FileOperation.SaveCompleteFile (MyApp.Client.InternalModel.Inspection localInspection, MyApp.Client.InternalModel.Inspection originalInspection, MyApp.Client.DbModels.FileDataEntity file, MyApp.Client.Common.FileWorkerCommand command) [0x00111] in C:\...\Source\MyApp.Client\Operations\FileOperation.cs:165 at MyApp.Client.Operations.FileOperation.UploadFilesToServer (MyApp.Client.InternalModel.Inspection localInspection, MyApp.Client.InternalModel.Inspection originalInspection, System.Collections.Generic.List1[T] commands) [0x00130] in C:....\Source\MyApp.Client\Operations\FileOperation.cs:92

Developer technologies .NET Xamarin
{count} votes

Accepted answer
  1. Andreas Brosten 116 Reputation points
    2021-11-23T07:08:31.737+00:00

    I think I found and solved the problem!
    I use the ServiceHost to handle my HttpClient cration, like this

      services.AddHttpClient<IMyApiClient, MyApiClient>()
      .ConfigureHttpClient(client =>
                {
                   client.Timeout = TimeSpan.FromMinutes(10);
                })
      // This line is what fixed the issue!
      .ConfigurePrimaryHttpMessageHandler(() => Startup.ServiceProvider.GetService<IMyPlatformSpecificService>().GetMessageHandler());
    

    And the implementation on android is just:

      public HttpMessageHandler GetMessageHandler()
      {
         return new Xamarin.Android.Net.AndroidClientHandler();
      }
    

    So, I guess, without this line, the message handler on android will be incorrectly set! (I guess it will use the System.Net.Http version).

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.