2010-08-13 41 views
9

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

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

10.0.0.1 www.bing.com 

当我尝试加载兵在浏览器(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贝尔的建议下,我尝试了System.Net跟踪。跟踪ONWebRequest失败,因为它应该。然而,只要我将追踪关闭行为恢复到意想不到的成功。在调试和发布模式下,我已经像以前一样在相同的机器上重现了这一点。

编辑2

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

+4

我猜你是通过你的网络中的代理工作。你的浏览器做什么? – 2010-08-13 21:08:31

+0

IE和FF都按预期运行(尝试从hosts文件中指示的服务器加载)。 – Nate 2010-08-13 21:30:51

+1

你尝试过'ipconfig/flushdns'吗? – Aren 2010-08-13 23:51:03

回答

7

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

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

这工作,因为你是问操作系统获取的IP地址www.bing.com

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

我希望这有助于。

乔纳森

+0

你是对的,我背后的公司代理,但我不知道我遵循你的逻辑。我期望'WebRequest.Create()'将展现与IE相同的行为,但它不会。 Bing.com在IE超时尝试加载10.0.0.1 – Nate 2010-08-14 13:53:18

+0

检查web.config以确保defaultProxy没有设置 - 删除这个固定上面给我。 – Elliott 2016-07-19 09:25:56

3

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

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一个不同的结果。”

+0

我正在使用VS2008和3.5 SP1。 'GetHostEntry'给了我和'GetHostAddress'一样的输出。我会研究跟踪。谢谢。 – Nate 2010-08-14 13:56:03

+0

打开System.Net跟踪您的建议。跟踪后,WebRequest按预期失败。追查它会回到意外的成功。思考? – Nate 2010-08-16 18:57:03

+0

这很奇怪 - 我没有一个好的答案。 Hans Passant和Jonathan Stanton对代理人有很好的意见。但是,如果IE使用代理并仍然考虑你的主机文件,那么在使用WebRequest时,hosts文件也应该覆盖代理。 我可以建议的唯一事情就是尝试禁用代理,正如mwalker的建议一样。您还可以尝试使用Wireshark或网络监视器等数据包嗅探器来查看线路上发生的情况 - 但我不确定这会有所帮助。如果您看到www.bing.com的DNS请求,则表示它没有使用hosts文件,但不能解释原因。 – 2010-08-16 20:53:49

2

This stackoverflow answer具有快速和肮脏的CONFIGS到.NET中停用代理。把它放在你的web.config或app.config中,然后System.Web不会寻找底层系统来获得它的代理配置。

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 
}