2013-08-22 27 views
1

我正在寫一個Java HTTP服務器。我認爲整個服務器正在運行,它正在使用線程。但是,我意識到將請求讀入BufferedReader的代碼片段並不一致。BufferedReader不一致地掛在我的套接字的輸入流上

這裏是讀取傳入的請求的代碼:

private String receive(WebSocket webSocket) throws IOException { 
    int chr; 
    System.out.println("Receiving!"); 
    StringBuffer buffer = new StringBuffer(); 

    while ((chr = webSocket.in().read()) != -1) { 
    buffer.append((char) chr); 
    if (!webSocket.in().ready()) 
     break; 
    } 
    return buffer.toString(); 
} 

我的網頁套接字類只是包裝Socket和提供了一種在和出。我這樣做,以便我可以嘲笑插座並測試我的服務器。

WebSocket的類看起來是這樣的:

package http.server.socket; 

import java.io.*; 
import java.net.Socket; 

public class SystemSocket implements WebSocket { 
    private Socket theConnection; 
    private BufferedReader in; 
    private OutputStream out; 

    public SystemSocket(Socket theConnection) throws IOException { 
    this.theConnection = theConnection; 
    in = new BufferedReader(new InputStreamReader(theConnection.getInputStream())); 
    out = new BufferedOutputStream(theConnection.getOutputStream()); 
    } 

    public BufferedReader in() throws IOException { 
    return in; 
    } 

    public OutputStream out() throws IOException { 
    return out; 
    } 

    public void close() throws IOException { 
    in.close(); 
    out.close(); 
    theConnection.close(); 
    } 
} 

的問題是,與每個URL用戶在瀏覽器中輸入,兩個請求是由 - 一個請求的頁面,另一個用於圖標。有時 - 看起來 - favicon的請求沒有進入,線程掛起。

這是我必須打印到控制檯一些調試信息,當事情右

Receiving! 
Receiving! 
REQUEST STRING = GET /color_picker.html HT 
[20130821 20:29:23] REQUEST: http://localhost:5000/color_picker.html 
[20130821 20:29:23] PAGE RENDERED 
REQUEST STRING = GET /favicon.ico HTTP/1.1 
[20130821 20:29:23] REQUEST: http://localhost:5000/favicon.ico 
[20130821 20:29:23] PAGE RENDERED 

「接收」每當要求越來越閱讀是越來越打印消息。所以,在這種情況下,「接收」消息被打印兩次,兩個請求進來,兩件事情被渲染。但隨後,在同一頁(但在不同的時間)將做到這一點(後約10秒)

Receiving! 
Receiving! 
REQUEST STRING = GET /color_picker.html HTTP/1.1 
[20130821 20:41:25] REQUEST: http://localhost:5000/color_picker.html 
[20130821 20:41:25] PAGE RENDERED 
REQUEST STRING = 
Exception in thread "ServerThread" java.lang.ArrayIndexOutOfBoundsException: 1 
    at http.request.Parser.setRequestLineData(Parser.java:42) 
    at http.request.Parser.setRequestHash(Parser.java:27) 
    at http.request.Parser.parse(Parser.java:13) 
    at http.request.Request.get(Request.java:18) 
    at http.server.ServerThread.run(ServerThread.java:39) 

以後的所有錯誤都是因爲請求字符串爲空。但我無法弄清楚爲什麼請求字符串爲空。我甚至無法弄清楚如何調試。

任何人都可以幫忙嗎?

另外需要注意的是,如果第二請求字符串不馬上來,用戶可以請求一個新的URL,這將導致第二個掛起進程來完成(所以後來第四請求的URL會是什麼掛起)。所以,只有當用戶停止請求時,在大約10秒後的最後一次請求中,我會得到錯誤。有時我可以請求20個不同的頁面,只有當我停止請求頁面並等待幾秒鐘後,我纔會看到一個錯誤。我認爲這是發生了什麼?

UPDATE:

%的要求,這裏是setRequestLineData()方法:

private void setRequestLineData() { 
    requestHash = new HashMap<String, String>(); 

    if (requestLineParts.length == 3) { 
    requestHash.put("httpMethod", requestLineParts[0]); 
    requestHash.put("url", requestLineParts[1]); //line 42 
    requestHash.put("httpProtocol", requestLineParts[2]); 
    } 
    else { 
    requestHash.put("httpMethod", requestLineParts[0]); 
    requestHash.put("url", requestLineParts[1]); 
    requestHash.put("queryString", requestLineParts[2]); 
    requestHash.put("httpProtocol", requestLineParts[3]); 
    } 
} 

UPDATE:

我想我找到了更多關於到底是怎麼回事在這裏與我的導師的幫助。他的想法是,一旦收到請求,瀏覽器立即啓動另一個請求,以減少下一次請求的加載時間。這聽起來對我來說似乎合理,因爲我可以一頁接一頁地加載頁面,但是在請求最後一頁之後只有大約10秒鐘,我得到一個錯誤。目前,我正在處理這個與自定義異常,但我正在一個更好的解決方案。感謝所有的幫助傢伙!

+1

'http.request.Parser'是你的課程嗎?請向我們展示'setRequestLineData()'方法。 –

+0

請注意爲什麼downvote?如果你讓我知道,我仍然可以幫忙。 –

+0

我沒有讓你失望@MarioRossi。抱歉。 – Kelly

回答

3

ready()對消息結束不是有效的測試。它只會告訴你是否有數據可以被讀取而不被阻塞。 TCP不是面向消息的協議,它是一種字節流協議。如果你想要消息,你必須自己實現它們,例如作爲行,長度值元組,長度值元組,序列化對象,XML文檔,...

如果有任何正確的使用ready()(或available()),並且這不是其中之一。

+0

謝謝你,EJP。根據Java Docs,「底層流的就緒方法返回false,表示進一步的輸入請求會阻塞。」看起來這個流是空的並且阻塞了。所以我正在使用該命令來打破它是否確實阻塞。我也嘗試過在另一個while循環中檢查ready()的while循環,但它不起作用。你有另外一個建議嗎?我在正確的軌道上嗎? – Kelly

+0

關鍵是阻塞與消息完成無關。你必須繼續閱讀,直到你有一個完整的信息,並準備好()不能幫你。如果獲得競爭性消息涉及阻止,那就這樣做。 – EJP

相關問題