System.Net.WebRequest不尊重主机文件

时间:2010-08-13 20:46:21

标签: c# .net hosts

有没有办法让System.Net.WebRequestSystem.Net.WebClient尊重hostslmhosts文件?

例如:在我的主机文件中,我有:

10.0.0.1  www.bing.com

当我尝试在浏览器(IE和FF)中加载Bing时,无法按预期加载。

Dns.GetHostAddresses("www.bing.com")[0]; // 10.0.0.1 
WebRequest.Create("http://10.0.0.1").GetResponse(); // throws exception (expected)
WebRequest.Create("http://www.bing.com/").GetResponse(); // unexpectedly succeeds

类似地:

WebClient wc = new WebClient();
wc.DownloadString("http://www.bing.com"); //succeeds 

为什么System.Net.Dns会尊重主机文件但System.Net.WebRequest会忽略它?我需要更改什么才能使WebRequest尊重hosts文件?

其他信息:

  • 如果我禁用IPv6并将我的IPv4 DNS服务器设置为127.0.0.1,则上述代码按预期工作(失败)。但是,如果我将正常的DNS服务器添加为备用服务器,则会恢复意外行为。
  • 我在3个Win7和2个Vista盒子上重现了这个。唯一不变的是我公司的网络。
  • 我正在使用.NET 3.5 SP1和VS2008

修改

根据@Richard Beier的建议,我尝试了System.Net追踪。跟踪开启时,WebRequest会失败。但是,只要我将跟踪关闭,行为就会恢复到意外的成功。我在调试和发布模式下都在以前的机器上重现了这一点。

修改2

事实证明这是公司代理给我们带来的问题。我们的解决方案是我们的测试机器的自定义代理配置脚本,其中“bing.com”指向DIRECT而不是默认代理。

4 个答案:

答案 0 :(得分:7)

我认为@Hans Passant在这里发现了这个问题。看起来你在IE中有一个代理设置。

Dns.GetHostAddresses("www.bing.com")[0]; // 10.0.0.1  

这是有效的,因为您要求操作系统获取www.bing.com的IP地址

WebRequest.Create("http://www.bing.com/").GetResponse(); // unexpectedly succeeds

这是有效的,因为您要求框架从服务器名称获取路径。该框架使用IE前端使用的相同引擎和设置,因此如果您的公司已通过GPO指定您使用公司代理服务器,那么代理服务器将解析www.bing.com而不是您的IP地址。

WebRequest.Create("http://10.0.0.1").GetResponse(); // throws exception (expected) 

这有效/失败,因为您已要求框架从特定服务器(通过IP)获取网页。即使您有代理集,此代理仍然无法连接到此IP地址。

我希望这会有所帮助。

乔纳森

答案 1 :(得分:3)

我在Windows 7上使用VS 2010,我无法重现这一点。我做了相同的hosts文件更改并运行了以下代码:

Console.WriteLine(Dns.GetHostAddresses("www.bing.com")[0]);             // 10.0.0.1     
var response = WebRequest.Create("http://www.bing.com/").GetResponse(); // * * *
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());

我在标有“* * *”的行上有例外。这是一个例外细节:

System.Net.WebException was unhandled
  Message=Unable to connect to the remote server
  Source=System
  StackTrace:
       at System.Net.HttpWebRequest.GetResponse()
       at ConsoleApplication2.Program.Main(String[] args) in c:\Data\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 17
  InnerException: System.Net.Sockets.SocketException
       Message=A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.0.0.1:80
       Source=System
       ErrorCode=10060

可能这是早期.NET版本的问题,现在已经在.NET 4 / VS 2010中修复了?您使用的是哪个版本的.NET?

我还从2007年发现了这个thread,其他人遇到了同样的问题。那里有一些很好的建议,包括以下内容:

  • 开启system.net tracing

  • 使用Dns.GetHostAddresses()将其解析为IP,解决此问题。然后将IP放入URL中 - 例如“http://10.0.0.1/”。这可能不是你的选择。

在上面的帖子中,mariyaatanasova_msft还说:“HttpWebRequest使用Dns.GetHostEntry来解析主机,因此你可能会得到与Dns.GetHostAddresses不同的结果。”

答案 2 :(得分:2)

This stackoverflow answer具有快速和脏的配置,可以在.NET中禁用您的代理。将它放在web.config或app.config中,然后System.Web不会查找底层系统以获取其代理配置。

答案 3 :(得分:0)

您应该覆盖默认代理。 HttpWebRequest& WebRequest将设置默认代理(如果存在于Internet Explorer中,并且您的文件主机绕过

request.Proxy = new WebProxy();

以下只是代码示例:

try
{
   HttpWebRequest request = (HttpWebRequest)WebRequest.Create("www.bing.com");
   request.Proxy = new WebProxy();
   request.Method = "POST";            
   request.AllowAutoRedirect = false;

   HttpWebResponse response = (HttpWebResponse)request.GetResponse();               
   if (response.StatusCode == HttpStatusCode.OK)
   {
      //some code here
   }
}
catch (exception e)
{
   //Some other code here
}