HttpWebRequest vs Webclient(特殊场景)

cod*_*ter 7 html c# http

我知道这个问题已经在这个帖子中得到了回答,但我似乎无法找到细节.

在我的场景中,我正在构建一个控制台应用程序,它将密切关注任何更改的html页面源.如果发生任何更新/更改,我将执行进一步的操作.此外,我还会在每1秒后执行一次请求,或者在上一次请求完成后立即执行请求.

我似乎无法弄清楚我应该使用HttpWebRequestWebClient下载html页面源并执行比较?在我看来,您认为什么是理想的解决方案?速度和可靠性都:)

Dyp*_*ppl 14

我会选择,HttpWebRequst因为它不是抽象的,而且可以让你轻松搞砸HTTP params.例如,如果服务器返回"文件未更改",则可以选择不下载整个页面.

如果您向请求添加一些参数IfModifiedSince(可能是HEAD或GET请求),则服务器可能会返回响应代码304 - NOT MODIFIED.有关进一步说明,请参阅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;    
    }
}
Run Code Online (Sandbox Code Playgroud)

true如果页面自dateTime日期以后修改,则此方法应返回,false如果不是.如果你发出一个HEAD请求,并且服务器返回304 - NOT MODIFIED(这有点不幸),GetResponse方法将抛出一个.我们必须确保它不是其他一些Web连接问题,这就是为什么我检查Web异常的状态和响应中的HTTP状态.如果有任何其他原因引起异常,我们就把它扔得更远.WebException

Console.WriteLine(IsResourceModified("http://example.com", new DateTime(2009)));
Console.WriteLine(IsResourceModified("http://example.com", DateTime.Now));
Run Code Online (Sandbox Code Playgroud)

此示例代码生成输出:

True
False
Run Code Online (Sandbox Code Playgroud)

注意:请务必阅读Jim Mischel对此答案的补充,因为他对此技术提出的建议很少.


Jim*_*hel 9

我打算将此作为评论@Dyppl的回应,但它变得太长了.

Dyppl的反应通常是很好的建议,以及我将如何解决这个问题.但是,您应该记住一些事项.

首先,没有理由做一个HEAD请求,然后是一个GETif页面是否被修改过.您可以GET使用IfModifiedSince标头集执行操作,服务器将返回整个页面或304.执行第HEAD一个操作,然后执行'GET`,最终会向服务器发出两个请求,这样做会破坏大部分目的.条件请求.

其次,您应该将IfModifiedSince属性设置为LastModified上一个响应返回的值(即HttpWebResponse.LastModified),因为服务器的时间可能与您的计算机不同步.此外,我发现大部分网站,特别是那些生成内容的网站(如WordPress博客)都存在.它们总是在LastModified标题中返回当前日期/时间.因此,If-Modified-Since对这些网站进行检查没有任何好处.

如果您知道该站点位于并始终返回当前日期/时间,则可以ContentLength在下载时跟踪从页面返回的标题.然后,当您要检查页面是否已更改时,请执行HEAD请求并ContentLength使用保存的值检查返回的标头.如果它们匹配,则页面不太可能发生变化.如果它们不匹配,GET请执行更新页面副本并保留新页面的请求ContentLength.

如果页面已经改变,该技术的缺点是需要两个请求.它在所有服务器上也不是100%可靠.有些会ContentLengthHEAD请求返回不同的内容,有些则根本不会返回有效内容ContentLength.也就是说,我发现它对大量网站都有效.