2008-11-11 123 views
3

我們有一個相當複雜的處理圖像的httphandler。基本上它以任何要求的大小流式傳輸圖像的任何部分。有些客戶端沒有任何問題使用這個處理程但是我們有一個位置給我們帶來了問題,現在它也給我的開發環境帶來了問題。HttpHandler響應永遠不會返回

會發生什麼情況是客戶端在某些請求中從不接收任何內容。所以請求1和2都很好,但請求3和4永不結束。

  • 在調試時,我可以看到服務器已準備就緒並已完成請求。
  • 客戶端上。然而其結果仍在等待(與fiddler2調試表明,有沒有接收到響應)

,我們使用以流的圖像中的代碼是

 if (!context.Response.IsClientConnected) 
     { 
      imageStream.Close(); 
      imageStream.Dispose(); 
      return; 
     } 

     context.Response.BufferOutput = true; 
     context.Response.ContentType = "image/" + imageformat; 

     context.Response.AppendHeader("Content-Length", imageStream.Length.ToString()); 

     if (imageStream != null && imageStream.Length > 0 && context.Response.IsClientConnected) 
      context.Response.BinaryWrite(imageStream.ToArray()); 

     if (context.Response.IsClientConnected) 
      context.Response.Flush(); 

     imageStream.Close(); 
     imageStream.Dispose(); 

的的ImageStream是帶有圖像內容的MemoryStream。

在對response.Flush()的調用之後,我們做了一些更多的清理工作,並將總結寫入事件日誌。

我們在每次請求後都會調用GC.Collect(),因爲我們在內存中使用的對象變得非常大。我知道這不是一種好的做法,但它會給我們帶來麻煩嗎?

在IIS 5(Win XP)和IIS 6(Win 2003)都沒有返回請求的問題,我們使用.NET Framework v2。

回答

2

客戶端將限制同時要求它會讓任何一個服務器的數量。此外,當從需要會話狀態的資源(默認)請求時,其他請求會話狀態的資源將被阻塞。

使用HttpWebResponse時,您必須處理該對象或其GetResponseStream方法返回的流以完成連接。

你的代碼很混亂。您已開啓緩衝,設置內容長度並使用了沖洗。這會導致一些奇怪的HTTP標頭。通常在你使用緩衝的情況下,將Content-Length頭的設置留給ASP.NET來處理。

當您使用flush ASP.NET假定您可能隨後發送更多數據。在這種情況下,它將使用分塊傳輸。一旦響應完成,最後一組標題被髮送給最後一個組塊,每個組塊作爲它自己的長度標題,並且內容的總長度從這些派生出來。第一塊應該是而不是有一個Content-Length頭,但是你的代碼添加了這個頭。

如果關閉緩衝和泵字節到輸出流自己然後你應該設置Content-Length頭自己,因爲有效的緩衝關閉意味着你正在服用的正是被髮送到客戶端的責任。 Marc的代碼就是這樣一個泵的簡單例子,儘管我會使用更大的緩衝區,或者在MemoryStream上,WriteTo方法會更有效率。

4

首先,有更好的方法來處理整個事物使用數組的流(即MemoryStream可能在此不必要)。

我會設想一個循環:

const int BUFFER_SIZE = 4096; // pick your poison 
bute[] buffer = new byte[BUFFER_SIZE]; 
int bytesRead; 

while((bytesRead = inStream.Read(buffer, 0, BUFFER_SIZE)) > 0) 
{ 
    outStream.Write(buffer, 0, bytesRead); 
} 

你也應該用(.Response.BufferOutput = false)禁用緩衝做到這一點。

重新提出這個問題,我的懷疑是你沒有寫足夠的數據/關閉響應(.Response.Close())。

+0

這不是解決方案,但仍然有用! – 2008-11-11 11:54:15

+0

但是,如果您擁有MemoryStream,則有一種更簡單的方法:MemoryStream.WriteTo(Stream) – 2008-11-11 12:37:03

2

垃圾收集不應該是問題。你爲什麼設置BufferOutput爲true?由於你只是想直接寫數據,所以我認爲將它設置爲false會更合適。

我建議你在診斷中降低一個級別:使用Wireshark來查看網絡級別正在發生的事情。 Fiddler非常適合HTTP級別,但有時您需要更多的細節。

0

我們還使用WebRequests來收集更多信息。那些阻止了連接。在WebResponses周圍使用這個技巧。

using (HttpWebResponse test_resp = (HttpWebResponse)test_req.GetResponse()) 
{ 
} 

我不知道,那些可能會阻止其他請求等...

相關問題