Xamarin HTTP 请求超时 [英] Timeouts in Xamarin HTTP requests

查看:39
本文介绍了Xamarin HTTP 请求超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

晚上好!

我试图清理/优化一些代码,最终发现了Xamarin HTTP 请求超时 的问题(如我的原始线程中所述:异步下载和反序列化).

I was trying to clean/refine some code and ended up finding issues with timeouts in Xamarin HTTP requests (as described in my original thread: Async Download and Deserialize).

发现问题(仅使用 Xamarin.Android 测试;不了解 iOS):

当无法访问主机(例如,离线本地服务器)时,GetAsync 会在大致3 分钟,消息错误:连接失败(连接超时).内部异常是 System.Net.Sockets.SocketsException(完整日志在这里:http://pastebin.com/MzHyp2FM).

When a host cannot be reached (e.g., an offline local server), GetAsync throws a System.Net.WebException after roughly 3 minutes with the message Error: ConnectFailure (Connection timed out). The Inner exception is System.Net.Sockets.SocketsException (full log here: http://pastebin.com/MzHyp2FM).

代码:

internal static class WebUtilities
{
    /// <summary>
    /// Downloads the page of the given url
    /// </summary>
    /// <param name="url">url to download the page from</param>
    /// <param name="cancellationToken">token to cancel the download</param>
    /// <returns>the page content or null when impossible</returns>
    internal static async Task<string> DownloadStringAsync(string url, CancellationToken cancellationToken)
    {
        try
        {
            // create Http Client and dispose of it even if exceptions are thrown (same as using finally statement)
            using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(5) })
            {
                // should I always do this?
                client.CancelPendingRequests();

                // Issue here; Timeout of roughly 3 minutes
                using (var response = await client.GetAsync(url, cancellationToken).ConfigureAwait(false))
                {
                    // if response was successful (otherwise return null)
                    if (response.IsSuccessStatusCode)
                    {
                        // return its content
                        return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                }
            }
        }
        // TODO: split exceptions?
        catch (Exception ex) when (ex is System.Net.Sockets.SocketException ||
                                    ex is InvalidOperationException ||
                                    ex is OperationCanceledException ||
                                    ex is System.Net.Http.HttpRequestException)
        {
            WriteLine("DownloadStringAsync task has been cancelled.");
            WriteLine(ex.Message);
            return null;
        }

        // return null if response was unsuccessful
        return null;
    }
}

调用方法:

internal static async Task CallAsync(string url)
    {
        using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
        {
            var token = cts.Token;
            token.ThrowIfCancellationRequested();

            string result = await WebUtilities.DownloadStringAsync(url, token).ConfigureAwait(false);
        }
    }

设置 client.Timeout 似乎不起作用.

Setting client.Timeout doesn't seem to work.

不管怎样,不应该在 10 秒后取消取消令牌吗?

这个超时问题发生在:

  • 一个离线/无法访问的 IP 地址(在我的例子中是一个离线本地服务器例如 192.168.1.101:8080) 被请求(即使用 GetAsyncSendAsyncGetResponseAsync)

代码在以下情况下运行良好:

  • 请求来自桌面客户端(例如,WPF).如果IP 离线/无法访问它会非常快地抛出 4 个异常(无法建立连接,因为目标机器主动拒绝了它).
  • The request is made from a desktop client (e.g., WPF). If the IP is offline/unreachable it throws 4 exceptions really fast (No connection could be made because the target machine actively refused it).

结论

Xamarin 似乎在 Http 请求中存在一些错误(至少有超时?),因为它们没有给出预期的结果.从我读到的内容来看,它可能已经存在了几年(自 2012 年或 2013 年以来).

Xamarin seems to have some bugs in Http requests (with Timeouts at least?), as they do not give the expected results. And from what I have read, it could be something that has been around for few a years (since 2012 or 2013).

Xamarin 单元测试也没有真正的帮助:https://github.com/xamarin/xamarin-android/blob/1b3a76c6874853049e89bbc113b22bc632ed5ca4/src/Mono.Android/Test/Xamarin.AndroidTesta/Xamarin.Android.

Xamarin unit testing doesn't really help either: https://github.com/xamarin/xamarin-android/blob/1b3a76c6874853049e89bbc113b22bc632ed5ca4/src/Mono.Android/Test/Xamarin.Android.Net/HttpClientIntegrationTests.cs

编辑

  • Timeout = TimeSpan.FromMilliseconds(1000) - 有效
  • Timeout = Timeout = TimeSpan.FromSeconds(1) - 不起作用 (?????)
  • Timeout = TimeSpan.FromMilliseconds(2000)(及以上) - 不工作
  • Timeout = TimeSpan.FromMilliseconds(1000) - works
  • Timeout = Timeout = TimeSpan.FromSeconds(1) - doesn't work (?????)
  • Timeout = TimeSpan.FromMilliseconds(2000) (and above) - doesn't work

有什么想法吗?谢谢!

推荐答案

我发现更改 Android 的 http 客户端设置解决了我的问题.
解决问题:

I found that that changing the http client settings for Android resolved my issue.
To solve the issue:

  • HttpClient实现到AndroidClientHandler
  • SSL/TLS 实现到原生 TLS 1.2+
  • from HttpClient implementation to AndroidClientHandler
  • from SSL/TLS implementation to Native TLS 1.2+

在 Xamarin Android 项目选项中.默认"值使用 Mono 自己的客户端导致了问题.

In Xamarin Android project options. "Default" values were using Mono's own client which caused the problem.

我发布了更多细节这里.

这篇关于Xamarin HTTP 请求超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆