2012-03-03 29 views
4

作爲一項挑戰,我已經在Java中實現了一個基本的Web服務器。當我打開原始的InputStream時,我立即進入一個阻塞讀取,它將整個400或HTTP請求字節讀入一個字節數組。這是有效的,但是我不會檢查更多的數據,只需在發送響應後關閉套接字即可。從HTTP服務器中的套接字讀取的推薦方式

我想知道是否有更健壯的方式來做到這一點,以免錯過客戶端的任何數據。我想一次讀取一個字節,直到read返回流結束。然而,它反而有時塊時,有沒有更多的數據和混淆爲public abtract int InputStream.read() JavaDoc中說:

If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.

所以它意味着,如果到達流的末尾,有兩種情況:返回-1和阻塞。我看到阻擋。

我的問題是,使用像HTTP這樣的協議,您應該如何從套接字中讀取數據,並且您如何知道在這種連接中您將獲得的所有數據?

回答

6

您引用的JavaDoc確實是而不是意味着如果到達流末尾,可能會發生兩件事。它不會說讀取塊流檢測結束,但直到流檢測結束。一旦檢測到,返回-1。

這解釋了您正在觀察的行爲:未檢測到流結束並且讀取被阻止。一旦連接關閉,就會檢測到流的結束,但由於客戶端在發送請求後沒有立即關閉連接,因此它未關閉。它必須保持開放才能收到答覆。

爲了確保您接收到客戶端的所有數據,您應該解析它們的HTTP請求,直到您看到標頭(雙行換行符)加上標頭中指定的任何數據量(如果有)爲止。

如果您想避免阻止查看java.niochannels(特別是SocketChannel)。

+2

實現HTTP協議是沒有其他選擇的。 HTTP協議告訴你如何識別請求的結束。您應該繼續閱讀,直到您收到完整的請求。 – 2012-03-03 02:02:38

+0

準確地說,沒有辦法確定客戶端是否已經發送了所有他們想要發送的僅指傳輸層設施的數據。必須要求應用層回答這個問題。 – 2012-03-03 02:05:02

+0

很好的解釋。現在有道理。那麼你會一次讀取一個字節,直到你到達頭部的末尾? – ScrollerBlaster 2012-03-03 02:10:56

相關問題