HttpWebRequest vs Webclient (特殊方案)
本文关键字:方案 vs Webclient HttpWebRequest | 更新日期: 2023-09-27 17:58:21
我知道这个问题之前在这个线程中已经回答过,但我似乎找不到细节。
在我的场景中,我正在构建一个控制台应用程序,该应用程序将密切关注 html 页面源代码的任何更改。如果发生任何更新/更改,我将执行进一步的操作。此外,我还会在每 1 秒后执行一次请求,或者在上一个请求完成后立即执行。
我似乎无法弄清楚我应该使用 HttpWebRequest
或WebClient
来下载 html 页面源代码并进行比较?您认为在我的情况下,什么是理想的解决方案?速度和可靠性:)
我会选择HttpWebRequst
,因为它没有那么抽象,并且可以让您经常摆弄HTTP参数。例如,如果服务器返回"文件未更改",它为您提供了不下载整个页面的选项。
如果您在请求中添加一些参数,例如IfModifiedSince
(可能是 HEAD 或 GET 请求(,服务器可能会返回响应代码 304 - 未修改。有关进一步说明,请参阅 HTTP 中的缓存说明。
关键是要确保仅在自上次获取页面以来实际修改时下载整个页面。大多数情况下它不会被更改(我想,如果不了解您的域就无法确定(,因此您只需要从服务器获得轻量级响应,该响应仅声明"此处没有任何更改"。
更新:演示IfModifiedSince
属性使用的代码示例:
bool IsResourceModified(string url, DateTime dateTime) {
try {
var request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.IfModifiedSince = dateTime;
request.Method = "HEAD";
var response = (HttpWebResponse)request.GetResponse();
return true;
}
catch(WebException ex) {
if(ex.Status != WebExceptionStatus.ProtocolError)
throw;
var response = (HttpWebResponse)ex.Response;
if(response.StatusCode != HttpStatusCode.NotModified)
throw;
return false;
}
}
如果页面自dateTime
日期以来被修改,则此方法应返回true
,如果没有,则返回false
。 如果您发出 HEAD 请求并且服务器返回 304 - 未修改(这有点不幸(,GetResponse
方法将抛出WebException
。我们必须确保这不是其他 Web 连接问题,这就是为什么我检查 Web 异常的状态和响应中的 HTTP 状态。如果其他任何事情导致异常,我们只是进一步抛出它。
Console.WriteLine(IsResourceModified("http://example.com", new DateTime(2009)));
Console.WriteLine(IsResourceModified("http://example.com", DateTime.Now));
此示例代码生成输出:
True
False
注意:请务必阅读Jim Mischel对这个答案的补充,因为他对这种技术几乎没有给出很好的建议。
我打算把它作为对@Dyppl回应的评论,但它变得太长了。
Dyppl的回答通常是很好的建议,也是我解决这个问题的方式。但是,您应该记住一些事项。
首先,没有理由执行HEAD
请求,然后GET
页面是否已修改。您可以使用 IfModifiedSince
标头集执行GET
,服务器将返回整个页面或 304。首先执行HEAD
,然后执行"GET",最终会向服务器发出两个请求,这违背了条件请求的大部分目的。
其次,应将 IfModifiedSince
属性设置为上一个响应返回的LastModified
值(即 HttpWebResponse.LastModified
(,因为服务器的时间可能与您的计算机不同步。此外,我发现很大一部分网站,尤其是那些生成内容的网站(如WordPress博客(都在撒谎。它们始终在LastModified
标头中返回当前日期/时间。因此,在这些站点上进行If-Modified-Since
检查没有任何好处。
如果您知道该网站存在谎言并始终返回当前日期/时间,则可以跟踪下载页面时从页面返回的ContentLength
标头。然后,当您想要检查页面是否已更改时,请执行HEAD
请求并使用保存的值检查返回的ContentLength
标头。如果它们匹配,则页面不太可能已更改。如果它们不匹配,请执行GET
请求以更新页面副本并保留新ContentLength
。
此技术确实存在缺点,即如果页面已更改,则需要两个请求。它也不是在所有服务器上都是 100% 可靠的。有些会为HEAD
请求返回不同的ContentLength
,有些根本不返回有效的ContentLength
。也就是说,我发现它对大量网站有效。