C# .net 中 Timeout 的处理及遇到的问题

C# 中 Timeout 的处理

前言

最近在项目中要实现一个功能,是关于 Timeout 的,主要是要在要在 TCP 链接创建的时间 和 整个请求完成的时间,在这两个时间层面上,若是超出了设置的时间,就抛出异常,程序中断。web

研究了一下项目的代码中,发如今使用HTTP协议,发送请求时,主要用的是微软的 Microsoft.Net.HttpWebRequest 这个类来发起请求和接收请求的。当时我隐约记得这个类怎么有点熟悉呀,好像还有 WebRequstHttpClient 这两个把,还没开始真正开始去了解TimeoutHttpWebRequest中 如何实现的,我先去看了看这三者到底有何不一样?c#

WebRequest , HttpWebRequest , HttpClient

WebRequest 是 一个抽象类,是HttpWebRequest 的父类。是.NET中请求和获取网络中的数据的一个类。api

HttpWebRequestWebRequest 的一个实现,不只对WebRequest中的属性和方法进行了支持,并且还有额外的方法经过Http协议来和服务端交互。网络

上面那两个如今在微软官方文档上都不推荐使用了,app

如今所推荐的是 HttpClient。因为项目中遗留以前使用的是HttpWebRequest,因此就在原来的基础上进行实现,况且的是在HttpClient中没有找到TCP链接创建的时间属性的设定。async

HttpClient 优势自没必要多说:性能

  • 链接池
  • 一次初始化,整个生命周期的重用
  • 和 .Net Core 的融合
  • 以及性能的提高等等

虽说性能可能提高了,若是你这样用,那也是凉凉url

using(HttpClient clinet = new HttpClient())
{
    var result = await client.GetAsync("http://aspnetmonsters.com");
    Console.WriteLine(result.StatusCode);
}

用完 Using 后,调用了IDispose接口。那下次仍是会从新初始化.net

这样使用就没问题了code

private static HttpClient Client = new HttpClient();

Timeout, ReadWriteTimeout

也多是我英文的理解能力有点差,在开始我就注意到这个类里面的这两个属性,可是我如何也没法和 TCP 创建前所用的链接时间 与 请求完成的时间联系起来。微软官方文档解释以下:

Timeout

Timeout is the number of milliseconds that a subsequent synchronous request made with the GetResponse method waits for a response, and the GetRequestStream method waits for a stream. The Timeout applies to the entire request and response, not individually to the GetRequestStream and GetResponse method calls. If the resource is not returned within the time-out period, the request throws a WebException with the Status property set to WebExceptionStatus.Timeout.

The Timeout property has no effect on asynchronous requests made with the BeginGetResponse or BeginGetRequestStream method.

ReadWriteTimeout:

The ReadWriteTimeout property is used when writing to the stream returned by the GetRequestStream method or reading from the stream returned by the GetResponseStream method.

Specifically, the ReadWriteTimeout property controls the time-out for the Read method, which is used to read the stream returned by the GetResponseStream method, and for the Write method, which is used to write to the stream returned by the GetRequestStream method.

设置实际上是很方便的,以下所示:

HttpWebRequest request = (HttpWebRequest)WebRequest.Creat("<your url>");

//Set timeout to 1s
request.Timeout = 1000; 

//Set ReadWriteTimeout to 3000
request.ReadWriteTimeout = 3000;

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

WebClient.Exception.Timeout 和 OperationCanceledException

最后在捕捉异常的时候,发现了一个很奇怪的地方,就是使用两段代码,却抛出了不一样的异常,

第一段代码:

HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com");
request.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse) request.GetResponse();

HttpWebRequest request2 = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com");
request2.Timeout = 1;
 HttpWebResponse response2 = (HttpWebResponse) request2.GetResponse();


//Exception
/*
Unhandled Exception: System.Net.WebException: The operation has timed out.
   at System.Net.HttpWebRequest.GetResponse()
*/

第二段

HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://www.alibabacloud.com");
request.Timeout = 5000;
HttpWebResponse response = (HttpWebResponse) request.GetResponse();

request = (HttpWebRequest) WebRequest.Create("https://www.cnblogs.com");
request.Timeout = 1;
response = (HttpWebResponse) request.GetResponse();

//Exception
/*
Unhandled Exception: System.OperationCanceledException: The operation was canceled.
   at System.Net.HttpWebRequest.GetResponse()
*/

初步估计的缘由是,Http 请求中 Keep-Alive的关系,还有一个多是 Timeout 的这个说明:

The Timeout applies to the entire request and response, not individually to the GetRequestStream and GetResponse method calls. 然而具体的还没搞清楚,还须要去验证。

后记

其实,设置这两个属性你可能只须要找到文档,分分钟就能够搞定,可是我为何会在这个过程遇到这些问题呢?一方面是对于C# 中网络请求的不熟悉,其次是找个时间,把之前的代码须要重构一下了,好比把HttpWebRequest 换成 HttpClient 等等。也让我加深了对Http协议的理解。

相关文章
相关标签/搜索