2014-01-31 182 views
11

我正在開發一個C#應用程序,它從Web服務器記錄數據。它將以下發布的請求發送到網絡服務器並等待響應。httpWebRequest(底層連接已關閉:連接意外關閉。)

/// <summary> 
    /// Function for obtaining testCgi data 
    /// </summary> 
    /// <param name="Parameters"></param> 
    /// <returns></returns> 
    private string HttpmyPost(string Parameters) 
    { 
     string str = "No response"; 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTestCGI); 
     request.Method = "POST"; 

     byte[] bytes = Encoding.UTF8.GetBytes(Parameters); 
     request.ContentLength = bytes.Length; 

     Stream requestStream = request.GetRequestStream(); 
     requestStream.Write(bytes, 0, bytes.Length); 
     requestStream.Close(); 

      WebResponse response = request.GetResponse(); 
      Stream stream = response.GetResponseStream(); 
      StreamReader reader = new StreamReader(stream); 

      try 
      { 
       var result = reader.ReadToEnd(); 
      stream.Dispose(); 
      str = result.ToString(); 
      reader.Dispose(); 
     } 
     catch (WebException ex) 
     { 
      //System.Windows.Forms.MessageBox.Show(ex.Message); 
      System.Diagnostics.Trace.WriteLine(ex.Message); 

     } 
     finally 
     { 
      request.Abort(); 
     } 
     return str; 
    } 

我收到錯誤

> "The underlying connection was closed: The connection was closed 
> unexpectedly" 

我試圖調試錯誤,我已經爲了從給定的Firefox檢查POST請求使用小提琴手。令我驚訝的是,每當菲德勒是我的程序完美工作。當我關閉小提琴手時,我有同樣的錯誤。

我懷疑由於Fiddler充當代理,它可能會改變一些設置。 我試過使用webclient,結果是一樣的。

當我嘗試在python中編寫請求時,所有的工作都應該沒有問題。我可以選擇安裝IronPython幷包裝特定功能,但我認爲這種矯枉過正和缺乏優雅,所以我正在尋求一種更精簡的方法。我懷疑這僅僅是一個設置調整。

我試過修改,在我的情況下它是無動於衷。

request.Accept 
request.ReadWriteTimeout 
request.Timeout 
request.UserAgent 
request.Headers 
request.AutomaticDecompression 
request.Referer 
request.AllowAutoRedirect 
//request.TransferEncoding 
request.Expect 
request.ServicePoint.Expect100Continue 
request.PreAuthenticate 
request.KeepAlive 
request.ProtocolVersion 
request.ContentType 

無論是否進行上述調整,代碼都可以在Fiddler捕獲數據時工作。 繼@EricLaw建議我看着延遲:

而且它可能在

WebResponse response = request.GetResponse(); 

更新中值得注意的是,該計劃產生的誤差。 我發現這篇文章 HttpWebRequest gets slower when adding an Interval 哪些建議轉動的Nagle算法。 現在沒有關閉的連接,雖然總體響應有一個小滯後(當我使用winforms,而不是異步)。

回答

0

一個建議和一個問題: 1)如果你真的想看看安裝Wireshark是怎麼回事。它會顯示你正在發送/接收的內容。這將使它有可能與小提琴手進行比較。 我想你錯過了一個頭,就像request.ContentType =「....」但只有wireshark會告訴你哪一個(通過你的工作替代發送,而不是你的HttpWebRequest發送)。

2)你是否在http響應內容中發現了錯誤,或者它是一個異常,如果它是一個異常,它會在catch語句中捕獲,還是在請求期間發生,在try語句之前?

+0

我已經安裝了Wireshark,並且已經確認標題是相同的。 :-( – NMech

-1

提琴手作爲一個互聯網代理。如果您的代碼在Fiddler運行時(也可能來自瀏覽器)工作,那麼您的代理設置可能有問題。

27

我想寫點關於如何小提琴手能「神奇地」在這裏解決的事情:http://blogs.telerik.com/fiddler/posts/13-02-28/help!-running-fiddler-fixes-my-app-

您遇到的問題,實際上是在.NET Framework本身就是一個錯誤。 HTTP的規則使服務器可以在發送第一個響應之後隨時關閉KeepAlive連接(例如,即使客戶端請求KeepAlive行爲,它也不需要接受連接上的另一個請求)。

.NET有它預計該服務器將包括Connection: close響應頭是否將關閉連接響應完成後的錯誤。如果服務器在沒有Connection: Close頭的情況下關閉連接(每個RFC2616完全有效),則在嘗試在連接上發送下一個請求時,.NET將遇到關閉連接,並且會拋出此異常。什麼.NET 正在做的是靜靜地創建一個新的連接,並重新發送該新連接的請求。

小提琴手,因爲它不關心,如果服務器關閉連接解決了這一問題,它不斷給客戶活着的連接。當客戶端發送第二個請求時,Fiddler嘗試重新使用與服務器的連接,注意到它已關閉,並靜默地創建一個新連接。

你可以在你的代碼緩解這個問題:

  1. 的要求禁用保活(這會降低性能)
  2. 捕捉異常,並自動
  3. 重試更改服務器保持連接活得更長

方法#3只適用於如果您控制服務器,並且客戶端可能在使用後關閉連接的網關/代理之後,您應該也可以使用方法2。

+0

我修改了下面的代碼,在try catch中封裝了請求的全部內容(並且還添加了一個最大計數器),並且如您所建議的,如果我嘗試幾次,最終我會得到期望的結果。 (我也添加了 ** request.ServicePoint.Expect100Continue = false; **) 但是成功之前的重試次數似乎是隨機的,這是否正常? – NMech

+0

不幸的是,選項3沒有提供給我。 1似乎可以緩解這個問題 由於數據量在這個應用程序中對我來說是一個問題,你會推薦使用不同的東西 - 比如一個封裝的ironPython函數 - 來獲取數據,然後像往常一樣繼續嗎? – NMech

+0

你應該剖析應用程序Keep-Alive被禁用並查看影響是什麼;關鍵變量*延遲*和*請求數*超過實際數據量。 – EricLaw

相關問題