2012-08-06 19 views
1

寫到以下列方式的HTTP請求的響應: response.getOutputStream().write()確保`response.getOutputStream()寫()`接收

我想確保客戶端接收它。

它必須可能,因爲TCP發送確認。

這個要求也意味着寫入必須是一個阻塞操作(這對我來說很好!)。

那麼我怎麼知道它是否以上述方式完成(我懷疑它不是)?任何保證它的規範? 有什麼辦法可以做到這一點?我在Tomcat 6

... PS,我的意思是任何方式除了使得客戶在另一個HTTP請求發送:)這個確認

回答

0

首先,你可以確保你刷新輸出流緩衝區:

response.getOutputStream().flush(); 

它保證數據實際發送出去。 TCP將確保它到達,否則會給你的服務器一個錯誤,這將會導致IOException異常。

因此,簡而言之,如果您可以編寫並且不會收到錯誤,您的客戶端確實會收到數據。至少在TCP堆棧上。客戶顯然負責消費該消息。

TCP提供數據完整性和交付保證。它將繼續重發,直到接收方確認接收到數據包。但是所有這些都發生在TCP棧內。你的代碼可以假設它發生了,或者你收到了一個錯誤。只有這兩種情況是可能的。

此外,您可能希望確保關閉輸出流,否則您的客戶端可能會坐在那裏緩衝數據,直到它收到流結束。

我希望這有助於

+0

不正確。 Downvote。 – EJP 2012-08-06 02:51:35

-1

TCP只知道數據已被對方接收。它不知道對等的應用程序已收到數據。而且TCP寫入是異步的,所以在寫入或刷新返回到發送應用程序之後很長時間就可以檢測到錯誤。

應用程序可以通過另一個HTTP事務確認接收,但HTTP應該是無狀態的,這樣做會違反該規則。

我建議你看看'兩軍問題'。

你應該做的是做你的交易idempotent(查看)然後確保交易發生是客戶的責任。如果客戶沒有得到答覆,他應該只重複交易。對重試次數設定一個下限,比如說兩到三次。

+0

+1很好的答案!然而,你說'HTTP應該是無狀態的'而'沒有得到響應,他應該只重複事務',因爲,我怎麼會得到一個響應(我認爲*你的意思是「服務器」而不是「客戶端「)而不發出另一個HTTP請求。 – Poni 2012-08-06 10:29:44

+0

此外,誰說」HTTP是**應該** ......「..有」會議「等」使它有狀態......無論如何不是。 – Poni 2012-08-06 10:30:58

+0

所以,基本上你建議,爲了使這個消息傳遞系統(這正是它是什麼)冪等的,我更好地移動到客戶端的處理,同時使它也確認明確接收消息,正確? – Poni 2012-08-06 10:33:37

-1

你確定這是你想要的嗎?測試寫入是否成功? TCP旨在確保其正常工作,如果數據包發生故障,您將開始獲取斷開連接和IOExeceptions。事實上,你會得到RunTimeException。做到這一點的方法是將回復發回給源代碼。等到響應來臨。

當你等待時,確保你等待一段時間並放棄,這樣你就不會掛起。

假設你只想調試你的代碼。如果你想調試使用像嗅覺一樣的數據包嗅探器。相信我,一旦你的邏輯正確,你就不需要ack數據包。

+0

如果數據包失敗,您可能在TCP檢測到連接很久之前就關閉了連接,並且您肯定不會得到'RuntimeException'。 Downvote。 – EJP 2012-08-06 03:41:47

+0

從一個奇怪的問題開始。 TCP比UDP更好地傳送數據包。知道它是否收到確定的唯一方法是發送一個確認。 TCP本身發送ACK,所以實際上沒有必要。在極少數情況下,TCP連接會變壞,會引發RunTimeException。 – Siddharth 2012-08-06 12:02:17

+0

@Siddarth所有這些都是正確的,但你忽略了TCP寫入是異步的。寫入不會等到ACK回來:它只是將數據緩存到內核中的套接字發送緩衝區中。因此,除非錯誤情況已經從前一個I/O坐在那裏,這將需要幾秒鐘的時間,否則它將沒有任何理由拋出IOException,如同在答案中所述。因此,您不能僅僅依靠寫入IOException的缺失,因爲寫入已被確認。它沒有。你提到的RuntimeException是你想象力的一個幻象。 – EJP 2012-08-06 23:04:59