指定超时之前的HttpClient超时 [英] HttpClient timeouts before the timeout specified

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

问题描述

我正在使用WP8中的HttpClient并进行发布请求。我知道这个通话可能要花很长时间,因为我实际上是在模拟慢速网络场景。因此,我将 HttpClient.Timeout 相应地设置为5分钟。



但是,我得到了大约60s的超时。我认为超时无法正常工作。
我相信此问题中所述的WP存在问题:
HttpClient Portable返回WP8上找不到的404



它们使用了一种解决方法,但不适用于我的情况。我确实想等待很长时间。



我的问题:



1)是Bug / WP8的HttpClient问题,或者我没有正确设置?
2)您是否认为仍在使用HttpClient的解决方法?



我读到,也许HttpWebRequest是一个选项。但是,我相信HttpClient应该是这种简单方案的理想选择。



我的代码很简单:

 私有静态异步任务< HttpResponseMessage> PostAsync(Uri serverUri,HttpContent httpContent)
{
var client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(5);
返回等待客户端。PostAsync(serverUri,httpContent).ConfigureAwait(false);
}

服务器收到请求,正在处理时,客户端中止。 / p>

更新: HttpClient.PostAsyn 返回的 HttpResponseMessage 是此 {状态代码:404,ReasonPhrase:,版本:0.0,内容:System.Net.Http.StreamContent,标头:{Content-Length:0}} 。如我所说,服务器已找到并且正在接收数据并对其进行处理。

解决方案

经过一些搜索和测试之后,我我们得出的结论是,问题出在Windows Phone本身,并且有60秒的超时时间(与HttpClient无关),并且据我所知无法更改。请参阅 http: //social.msdn.microsoft.com/Forums/zh-CN/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout



在对服务器进行编程时,我将在上面提供的链接中尝试Darin Rousseau的建议,特别是先发送OK,然后进行更多处理。






更新:问题似乎是Windows Phone模拟器,如下所示:
http://social.msdn.microsoft .com / forums / wpapps / en-us / 6c114ae9-4dc1-4e1f-afb2-a6b9004bf0c6 / httpclient-doesnt-work-on-windows-phone?forum = wpdevelop 。以我的经验,如果60秒钟内没有听到任何声音,则tcp连接超时。






因此,我的解决方案是使用Http标头字符作为保持活动的方式。第一行Http标头响应始终以 HTTP / 1.0 开头。因此,我一一发送字符,它们之间的延迟小于60s。当然,如果响应准备就绪,剩下的所有内容都会立即发送出去。这会花一些时间,例如,如果每9个字符使用50s的延迟,我们将得到450s。



这是我所学学位的项目,所以我不建议这样做



顺便说一句,我也尝试使用其他字符代替标头的子字符串,例如空格字符,但这会导致违反http协议。



这是代码的主要部分:

  private const字符串Header1 = @ HTTP / 1.0; 
private int _keepAliveCounter = 0;
私有只读对象_sendingLock = new object();
私人布尔值_keepAliveDone = true;

private void StartKeepAlive()
{
Task.Run(()=> KeepAlive());
}

///< summary>
///使连接保持活动状态,并以一定的间隔发送http响应的第一个字符。
///这是适用于Windows Phone 8的黑客程序,需要在60秒的间隔内进行响应。
///< / summary>
private void KeepAlive()
{
try
{
_keepAliveDone = false;
_keepAliveCounter = 0;
while(!_keepAliveDone& _amp; _keepAliveCounter< Header1.Length)
{
Task.Delay(TimeSpan.FromSeconds(50))。Wait();
lock(_sendingLock)
{
if(!_keepAliveDone)
{
var sw = new StreamWriter(OutputStream);
sw.Write(Header1 [_keepAliveCounter]);
Console.Out.WriteLine(写保持活动状态的字符'{0}',Header1 [_keepAliveCounter]);
_keepAliveCounter ++;
sw.Flush();
}
}
}
_keepAliveCounter = 0;
_keepAliveDone = true;
}
catch(异常e)
{
//记录异常
Console.Out.WriteLine(发送keepalive时出错: + e.Message) ;
}
}

然后,实际处理发生在另一个线程中。



评论和批评家表示赞赏。


I'm using HttpClient from WP8 and do a Post request. I know the call may take long time as I'm actually simulating slow network scenarios. Therefore I set the HttpClient.Timeout accordingly to 5 minutes.

However, I get a Timeout at around 60s. I believe the Timeout is not working. I believe there is an issue with this for WP as stated in this question: HttpClient Portable returns 404 notfound on WP8.

They use a workaround but that does not applies to my scenario. I do actually want to wait for long time.

My questions:

1) Is it a bug/issue of HttpClient for WP8 or I'm not setting it properly? 2) Do you think of a workaround still using HttpClient?

I've read that maybe HttpWebRequest is an option. However, I believe HttpClient should be ideal for this 'simple' scenario.

My code is simple:

private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
    var client = new HttpClient();
    client.Timeout = TimeSpan.FromMinutes(5);
    return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}

The server receives the request and while is processing it, the client aborts.

UPDATE: The HttpResponseMessage returned by HttpClient.PostAsyn is this "{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}". As I said, the server is found and is receiving the data and processing it.

解决方案

After some search and some tests I've came to the conclusion that the problem is Windows Phone itself and that it has a 60 seconds timeout (irrespective of the HttpClient) and that cannot be changed to my knowledge. See http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.

As I'm programming the server as well, I will try the advice by Darin Rousseau in the link provided above, specifically to send an OK and then do some more processing.


UPDATE: The problem seems to be the Windows Phone emulator as stated here: http://social.msdn.microsoft.com/forums/wpapps/en-us/6c114ae9-4dc1-4e1f-afb2-a6b9004bf0c6/httpclient-doesnt-work-on-windows-phone?forum=wpdevelop. In my experience the tcp connection times-out if it doesn't hear anything for 60s.


Therefore my solution is to use the Http header characters as a way of keep alive. The first line Http header response always starts with HTTP/1.0. So I send the characters one by one with a delay <60s between them. Of course, if the response gets ready, everything that is left is sent right away. This buys some time, for instance if using a delay of 50s per 9 character we get about 450s.

This is a project for my degree so I wouldn't recommend it for production.

By the way, I also tried with other characters instead the sub string of the header, for instance space character, but that results in a http protocol violation.

This is the main part of the code:

    private const string Header1 = @"HTTP/1.0 ";
    private int _keepAliveCounter = 0;
    private readonly object _sendingLock = new object();
    private bool _keepAliveDone = true;

    private void StartKeepAlive()
    {
        Task.Run(() => KeepAlive());
    }

    /// <summary>
    /// Keeps the connection alive sending the first characters of the http response with an interval.
    /// This is a hack for Windows Phone 8 that need reponses within 60s interval.
    /// </summary>
    private void KeepAlive()
    {
        try
        {
            _keepAliveDone = false;
            _keepAliveCounter = 0;
            while (!_keepAliveDone && _keepAliveCounter < Header1.Length)
            {
                Task.Delay(TimeSpan.FromSeconds(50)).Wait();
                lock (_sendingLock)
                {
                    if (!_keepAliveDone)
                    {
                        var sw = new StreamWriter(OutputStream);
                        sw.Write(Header1[_keepAliveCounter]);
                        Console.Out.WriteLine("Wrote keep alive char '{0}'", Header1[_keepAliveCounter]);
                        _keepAliveCounter++;
                        sw.Flush();
                    }
                }
            }
            _keepAliveCounter = 0;
             _keepAliveDone = true;
        }
        catch (Exception e)
        {
            // log the exception
            Console.Out.WriteLine("Error while sending keepalive: " + e.Message);
        }
    }

Then, the actual processing happens in a different thread.

Comments and critics are appreciated.

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

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