在C#中调整HttpWebRequest连接超时

我相信经过长时间的研究和search,我发现我想要做的事情可能会更好地通过build立一个asynchronous连接,并在所需的超时后终止它。但是,我会继续问,无论如何!

快速代码片段:

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方法是在一个multithreading应用程序,我连接到大量的公司Web服务器。 在服务器没有响应的情况下, HttpWebRequest.GetResponse()大约需要20秒钟超时,即使我指定了仅5秒的超时时间。 为了定期通过服务器,我想跳过那些连接超过5秒的连接。

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

相信问题是WebRequest只有在请求被实际执行之后才会测量时间。 如果你提交多个请求到同一个地址,那么ServicePointManager将会限制你的请求,并且实际上只提交与默认值ServicePointManager.DefaultConnectionLimit相对应的ServicePoint.ConnectionLimit的值。 应用程序CLR主机将其设置为2,将ASP主机设置为10.因此,如果您有一个multithreading应用程序向同一主机提交多个请求,则只有两个实际上被放置在线路上,其余的则排队等候。

我没有把这个研究结果作为一个确凿的证据来certificate这是否真的发生了,但是在一个类似的项目中,直到我删除了ServicePoint限制之前,事情是非常糟糕的。

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

是的,你必须围绕WebRequest.BeginGetRequestStream (对于具有内容的POST )和WebRequest.BeginGetResponse (对于GET POSTS )编码你的应用程序。 同步呼叫不会扩展(我不会详细说明为什么,但是我确实很好的证据)。 无论如何, ServicePoint问题与此是正交的:排队行为也发生在asynchronous调用中。

对不起,对一个古老的线程,但我认为上面说的东西可能是不正确的/误导。

从我可以告诉.Timeout不是连接时间,它是HttpWebRequest和响应的整个生命所允许的总时间。 certificate:

我设置:

 .Timeout=5000 .ReadWriteTimeout=32000 

HttpWebRequest的连接和发布时间花了26ms

但随后的调用HttpWebRequest.GetResponse()超时4974毫秒,从而certificate5000毫秒是整个发送请求/获取响应设置的调用的时间限制。

我没有validationDNS名称parsing是否作为时间的一部分来衡量,因为这与我无关,因为这些工作都不是我真正需要它工作的方式 – 我的意图是在连接到系统时超时没有接受连接,如在请求的连接阶段失败所示。

例如:我愿意等待30秒的连接请求,有机会返回一个结果,但我只想烧10秒,等待发送一个请求,一个不正常的主机。

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

所以,在我看来:

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

更多信息: HttpWebRequest.ReadWriteTimeout属性

编辑:

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

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

(强调我的)

从HttpWebRequest.Timeout属性的文档:

域名系统(DNS)查询最多可能需要15秒才能返回或超时。 如果您的请求包含需要解决的主机名,并且将Timeout设置为小于15秒的值,则可能需要15秒或更长时间才会引发WebException,以指示请求超时。

是否有可能您的DNS查询是超时的原因?

无论我们尝试了什么,当我们检查的服务器停止运行时,我们无法在超过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; }