System.Net.WebRequest不遵守hosts文件

9
有没有一种方法可以让 System.Net.WebRequest 或者 System.Net.WebClient 遵守 hosts 或者 lmhosts 文件?
例如:在我的 hosts 文件中,我有:
10.0.0.1  www.bing.com

当我尝试在浏览器中加载Bing(包括IE和FF)时,它无法正常加载。
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会遵守hosts文件,但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
我猜你的网络中使用了代理。你的浏览器会怎样处理? - Hans Passant
IE和FF的行为都符合预期(尝试从主机文件中指定的服务器加载)。 - Nate
1
你尝试过使用 ipconfig /flushdns 命令吗? - Aren
是的,而且 ipconfig /displaydns 显示了主机文件中的条目。 - Nate
3个回答

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地址。

希望这可以帮助您。

乔纳森


你说得对,我是在公司代理后面,但我不确定我是否理解你的逻辑。我原以为 WebRequest.Create() 的行为与 IE 相同,但事实并非如此。在 IE 中,尝试加载 10.0.0.1 时,bing.com 会超时。 - Nate
检查 web.config 文件,确保没有设置 defaultProxy - 我移除了这个设置后问题得到解决。 - Elliott

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年的帖子(链接),其中有人遇到了同样的问题。那里有一些很好的建议,包括以下几点:
- 打开system.net跟踪 - 通过使用Dns.GetHostAddresses()将其解析为IP来解决该问题。然后将IP放入URL中,例如:http://10.0.0.1/。不过这可能对您来说不是一个选项。
在上述线程中,mariyaatanasova_msft还说:“HttpWebRequest使用Dns.GetHostEntry来解析主机名,因此您可能会从Dns.GetHostAddresses得到不同的结果”。

我正在使用VS2008和3.5 SP1。GetHostEntry给我与GetHostAddress相同的输出。我会研究一下跟踪。谢谢。 - Nate
根据您的建议,我打开了System.Net跟踪。在跟踪开启时,WebRequest按预期失败。而当跟踪关闭时,它又意外地成功了。您有什么想法? - Nate
非常奇怪 - 我没有一个好的答案。Hans Passant和Jonathan Stanton关于代理的观点很好。但是,如果IE使用代理并且仍然尊重您的hosts文件,则在使用WebRequest时,hosts文件也应该覆盖代理。我唯一能建议的是尝试禁用代理,如mwalker所建议的那样。您还可以尝试使用诸如Wireshark或Network Monitor之类的数据包嗅探器来查看线路上发生了什么 - 但我不确定这会有所帮助。如果您看到www.bing.com的DNS请求,则确认它没有使用hosts文件,但无法解释原因。 - Richard Beier

0

你应该覆盖默认代理。 如果Internet Explorer中存在默认代理,则HttpWebRequest和WebRequest将设置默认代理,而您的文件hosts将被绕过

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接