在C#中调整HttpWebRequest连接超时

时间:2009-09-30 22:20:49

标签: c# httpwebrequest timeout

我相信经过漫长的研究和搜索,我发现我想做的事情可能更好,通过设置异步连接并在所需的超时后终止它...但我会继续问反正!

快速代码段:

HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(url);
webReq.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse(); 
// this takes ~20+ sec on servers that aren't on the proper port, etc.

我有一个HttpWebRequest方法,它位于多线程应用程序中,我连接到大量公司Web服务器。如果服务器没有响应,HttpWebRequest.GetResponse()大约需要20秒才能超时,即使我指定的超时时间仅为5秒。为了定期通过服务器,我想跳过连接时间超过5秒的服务器。

所以问题是:“是否有一种简单的方法来指定/减少WebRequest或HttpWebRequest的连接超时?”

5 个答案:

答案 0 :(得分:57)

相信问题是WebRequest仅在实际发出请求后才测量时间。如果您向同一地址提交多个请求,那么ServicePointManager将限制您的请求,并且实际上只提交与相应ServicePoint.ConnectionLimit的值一样多的并发连接,默认情况下从ServicePointManager.DefaultConnectionLimit获取值}。应用程序CLR主机将此设置为2,ASP主机设置为10.因此,如果您有一个多线程应用程序向同一主机提交多个请求,则实际上只有两个请求在线路上,其余的排队等待。

我没有研究过这个确凿的证据,证明这是不是真的发生了,但是在一个类似的项目中,我发现事情是可怕的,直到我删除了ServicePoint限制。

要考虑的另一个因素是DNS查找时间。同样,我的信念没有得到确凿证据的支持,但我认为WebRequest 计算DNS查询时间与请求超时。 DNS查询时间可能会在某些部署中显示为非常大的时间因素。

是的,您必须围绕WebRequest.BeginGetRequestStream(包含内容的POST)和WebRequest.BeginGetResponse(适用于GET s POSTS s)。同步调用不会扩展(我不会详细说明原因,但我有确凿的证据)。无论如何,ServicePoint问题与此正交:排队行为也发生在异步调用上。

答案 1 :(得分:33)

很抱歉找到一个旧帖子,但我认为上面提到的内容可能不正确/误导。

据我所知.Timeout不是连接时间,它是HttpWebRequest和响应的整个生命周期所允许的总时间。证明:

我设置:

.Timeout=5000
.ReadWriteTimeout=32000

HttpWebRequest的连接和发布时间为26ms

但后续调用HttpWebRequest.GetResponse()在4974ms超时,从而证明5000ms是整个发送请求/获取响应调用集的时间限制。

我没有验证DNS名称解析是否作为时间的一部分进行了测量,因为这与我无关,因为这些都不是我真正需要它工作的方式 - 我的意图是在连接时更快地超时对于那些不接受连接的系统,如在连接请求的连接阶段,它们失败了。

例如:我愿意在有可能返回结果的连接请求上等待30秒,但我只想等待10秒钟等待向行为不端的主机发送请求。

答案 2 :(得分:19)

我后来发现有帮助的东西是.ReadWriteTimeout属性。除了.Timeout属性之外,这似乎最终减少了线程花在尝试从有问题的服务器上下载的时间。 .ReadWriteTimeout的默认时间是5分钟,对我的应用来说太长了。

所以,在我看来:

.Timeout =尝试建立连接所花费的时间(不包括查找时间) .ReadWriteTimeout =建立连接后尝试读取或写入数据所花费的时间

更多信息:HttpWebRequest.ReadWriteTimeout Property

修改

Per @ KyleM的评论,Timeout属性用于整个连接尝试,并在MSDN上阅读它显示:

  

Timeout是使用GetResponse方法进行的后续同步请求等待响应的毫秒数,GetRequestStream方法等待流。 超时适用于整个请求和响应,而不是单独应用于GetRequestStream和GetResponse方法调用。如果在超时期限内未返回资源,则请求将抛出WebException并设置Status属性到WebExceptionStatus.Timeout。

(强调我的。)

答案 3 :(得分:14)

来自HttpWebRequest.Timeout属性的文档:

  

域名系统(DNS)查询可以   最多需要15秒才能返回或   超时。如果您的请求包含   需要解决的主机名和   您将超时设置为小于的值   15秒,可能需要15秒或   抛出WebException之前的更多内容   表示您的请求超时。

您的DNS查询是否可能导致超时?

答案 4 :(得分:7)

无论我们尝试了什么,当我们检查的服务器关闭时,我们都无法将超时设置为低于21秒。

要解决此问题,我们将TcpClient检查结合起来,查看域是否处于活动状态,然后单独检查以查看URL是否处于活动状态

public static bool IsUrlAlive(string aUrl, int aTimeoutSeconds)
{
    try
    {
        //check the domain first
        if (IsDomainAlive(new Uri(aUrl).Host, aTimeoutSeconds))
        {
            //only now check the url itself
            var request = System.Net.WebRequest.Create(aUrl);
            request.Method = "HEAD";
            request.Timeout = aTimeoutSeconds * 1000;
            var response = (HttpWebResponse)request.GetResponse();
            return response.StatusCode == HttpStatusCode.OK;
        }
    }
    catch
    {
    }
    return false;

}

private static bool IsDomainAlive(string aDomain, int aTimeoutSeconds)
{
    try
    {
        using (TcpClient client = new TcpClient())
        {
            var result = client.BeginConnect(aDomain, 80, null, null);

            var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(aTimeoutSeconds));

            if (!success)
            {
                return false;
            }

            // we have connected
            client.EndConnect(result);
            return true;
        }
    }
    catch
    {
    }
    return false;
}