2012-02-09 129 views
4

我想用HttpWebRequest對象進行「長輪詢」。處理網絡斷開

在我的C#應用​​程序中,我使用HttpWebRequest發出HTTP GET請求。然後,我等待beginGetResponse()的響應。我正在使用ThreadPool.RegisterWaitForSingleObject等待響應或超時(1分鐘後)。

我已經設置了目標Web服務器需要很長時間才能響應。所以,我有時間斷開網線。

發送請求後,我拉網線。

當發生這種情況時,是否有辦法獲得異常?所以我不必等待超時?

而不是一個例外,超時(從RegisterWaitForSingleObject)發生在1分鐘超時已過期後。

有沒有辦法確定網絡連接故障?目前,這種情況與Web服務器花費1分鐘以上的時間進行響應的情況沒有區別。

回答

8

我找到了一個解決方案:

在致電beginGetResponse,我可以呼籲HttpWebRequest的以下內容:

req.ServicePoint.SetTcpKeepAlive(true, 10000, 1000) 

我認爲,這意味着閒置10秒後,客戶端會發送一個TCP「保持活躍」到服務器。如果網絡連接因網絡電纜被拉斷而關閉,則保持活動狀態將失敗。

所以,當拉線時,我保持活着在10秒內(最多)發送,然後發生BeginGetResponse的回調。在回調中,當我調用req.EndGetResponse()時,我會得到和異常。

我想這會打敗長輪詢的好處之一。由於我們仍在發送數據包。

2

我不認爲你會喜歡這個。向慢速服務器創建請求後,您可以測試Internet連接。

有很多方法可以做到這一點 - 從另一個請求到google.com(或您網絡中的某個IP地址)到P/Invoke。您可以在此處獲得更多信息:Fastest way to test internet connection

創建原始請求後,您將進入一個循環,檢查互聯網連接,並且直到互聯網關閉或原始請求返回(可以設置變量以停止循環)。

有幫助嗎?

+0

它有一點幫助,但它似乎像HttpWebRequest應該知道(遲早)如果它的TCP連接已經關閉。 – 2012-02-09 19:27:05

+0

爲什麼不擴展HttpWebRequest以添加此功能?但如果你問的是本地.NET框架,那麼不,我不認爲HttpWebRequest包含這樣的功能。 – Yannis 2012-02-09 19:37:16

3

我會讓你嘗試拉上這個插件。

ManualResetEvent done = new ManualResetEvent(false); 

void Main() 
{   
    // set physical address of network adapter to monitor operational status 
    string physicalAddress = "00215A6B4D0F"; 

    // create web request 
    var request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://stackoverflow.com")); 

    // create timer to cancel operation on loss of network 
    var timer = new System.Threading.Timer((s) => 
    { 
     NetworkInterface networkInterface = 
      NetworkInterface.GetAllNetworkInterfaces() 
       .FirstOrDefault(nic => nic.GetPhysicalAddress().ToString() == physicalAddress); 

     if(networkInterface == null) 
     { 
      throw new Exception("Could not find network interface with phisical address " + physicalAddress + "."); 
     } 
     else if(networkInterface.OperationalStatus != OperationalStatus.Up) 
     { 
      Console.WriteLine ("Network is down, aborting."); 
      request.Abort(); 
      done.Set(); 
     } 
     else 
     { 
      Console.WriteLine ("Network is still up."); 
     } 
    }, null, 100, 100); 

    // start asynchronous request 
    IAsyncResult asynchResult = request.BeginGetResponse(new AsyncCallback((o) => 
    { 
     try 
     {   
      var response = (HttpWebResponse)request.EndGetResponse((IAsyncResult)o); 
      var reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8); 
      var writer = new StringWriter(); 
      writer.Write(reader.ReadToEnd()); 
      Console.Write(writer.ToString()); 
     } 
     finally 
     { 
      done.Set(); 
     } 
    }), null); 

    // wait for the end 
    done.WaitOne(); 
}