在調用GetRequestStream(或BeginGetRequestStream)之前設置ContentLength屬性,然後將較少的字節寫入該流。如果您在獲取請求流後嘗試設置它,ContentLength將拋出。如果你沒有設置ContentLength,HttpWebRequest將緩衝頭部,直到流被關閉,以便它可以適當地設置ContentLength(或者,你可以使用SendChunked,但這對你不適用)。如果您希望對此進行最大限度的控制,請手動創建一個malormed請求或兩個請求,然後打開一個套接字到服務器上的端口80,並將請求寫入TCP流,然後讀取響應並檢查連接以查看它是否已關閉。
但是:我不認爲這個測試是一個好主意。問題如下:
客戶端向服務器發送請求。它聲稱內容將是100字節。然後它發送90個字節,然後停止發送,並保持連接打開。服務器讀取90個字節,然後等待剩下的時間,因爲客戶端說要發送100個字節。現在,客戶端發送第二個請求。服務器將如何處理新請求的前10個字節?
答案是,服務器會假定這些字節是前一個請求的一部分,並將它們視爲這樣,然後在啓動後10個字節開始讀取「新」請求,這顯然會導致格式錯誤的標題。服務器不會那樣,所以它會發送一個4xx錯誤,然後關閉連接。它關閉連接的原因是因爲它現在無法知道發送給它的數據是什麼意思,也無法恢復。另外,連接的關閉不會很優美,會突然發生,另一端提交第二個請求的HttpWebRequest(如果他們排隊等待,則排在第三或第四個請求)會拋出一個WebException,表示基礎連接已關閉,並讓您猜測原因。
這種情況導致連接被Expect 100-continue頭關閉,並且服務器返回100-繼續,然後是4xx,例如需要Auth時。即使它拒絕了請求,它仍然必須假定下一個字節是同一個請求的一部分,因爲它已經承諾通過發送100-continue來接收這些字節。如果它不服務該請求,或者客戶端想要取消請求並提交一個新請求(推測使用auth憑證),那麼它必須關閉連接並打開一個新連接。
最後,使用TCP測試網絡流中的EndOfStreamException對我來說根本沒有任何意義。 TCP不標記流的「結束」,它只是在寫入套接字時才發送數據。沒有「EOF」,沒有辦法檢測數據是否全部被傳輸,除非你知道需要多少數據。除非連接被關閉,否則TCP並不真正擁有「結束」,在這種情況下,根據您正在操作的堆棧中的哪個位置,您將得到一個WebException或一個SocketException。在協議中的任何傳輸錯誤都在winsock中處理。如果沒有更多的數據發送,連接的一端最終會向另一端發送一個保持連接,以確保連接實際上仍然打開,並且一臺主機不會丟棄它。如果Keepalive超時,連接將被關閉,並且您下次嘗試從中讀取時可能會收到WebException。鑑於所有這些工作如何,我只是不明白你將如何從這個測試中獲得任何價值。只需發送格式錯誤的請求並確保相應地處理錯誤,並將適當的4xx消息發送回客戶端並正確關閉連接即可。
我們的集成測試模擬客戶端。我們無法對接收方進行任何更改以方便測試。 – cfeduke 2009-08-25 16:35:31