我写了一个小型的Windows服务来检查网站的可用性。我注意到它由于 NIC 进入睡眠状态而失败,但即使在 NIC 唤醒后请求也无法恢复。
我可以通过简单地在检查站点的WinForm上使用"ipconfig/release"和"ipconfig/renew"来重现该问题。
这是代码:
private void checkSite()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(WebSite);
HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
request.CachePolicy = noCachePolicy;
request.AllowAutoRedirect = false;
request.Method = WebRequestMethods.Http.Head;
request.Timeout = 5000;
request.KeepAlive = false;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
UpdateResult(response.StatusCode + " --> " + response.StatusDescription);
}
}
catch (WebException ex)
{
UpdateResult(ex.Message);
}
finally
{
request = null;
GC.Collect();
}
}
启动checkSite()
工作,直到我尝试断开 NIC(ipconfig/release),之后它显然失败并The remote name could not be resolved: 'www.google.it'
.重新连接网卡(ipconfig/renew)后,该方法持续失败,并显示Unable to connect to the remote server
。 使其再次工作的唯一方法是关闭程序并重新启动它。
我错过了什么?
ps:我强制GC.Collect()
,因为该进程的已用内存在每次checkSite()
后都会增长(不知何故,即使每 2 分钟检查一次也不会收集)。
编辑:我发现请求ServicePoint正在存储DefaultProxy,正如我在app.config中要求的那样:
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true"/>
</system.net>
在"ipconfig/release"之后,ServicePoint丢失了有关代理的所有内容,并且"ipconfig/renew"不会更改ServicePoint中的任何内容,它没有使用代理。
编辑2:请求在此过程中丢失了默认代理:
第一个请求通过默认代理,如 app.config;
ipconfig /release
;发送第二个请求,不使用代理;
ipconfig /renew
;发送第三个请求,仍然不使用代理。
是否可以强制恢复默认代理? 我试过这个,但无济于事:
IWebProxy webProxy = WebRequest.DefaultWebProxy;
webProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Proxy = webProxy;
我能够通过重置catch
正文中的DefaultWebProxy来解决问题:
WebRequest.DefaultWebProxy = WebRequest.GetSystemWebProxy();
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
感谢理查德为我指明了正确的方向。