2010-08-13 48 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 
}