2016-09-03 54 views
1

當我寫接收HTTP請求的服務器(僅限GET方法,從學校簡化工作的一部分)爲什麼scanner.hasNext()塊讀取HTTP請求

我以前Socket類來獲取連接 我再使用InputStream以及Scanner來讀取http請求。

但是,當我正在使用hasNext()逐行讀取http請求標題時。該程序掛在hasNext(),等待更多的投入,即使它已經消耗了所有線路。

下面是我readRequest方法:

public void readRequest(Socket client) throws BadRequestException { 
    StringBuilder builder = new StringBuilder(); 

    try { 
     Scanner sc = new Scanner(client.getInputStream()); 
     sc.useDelimiter("\\r\\n"); 

     while(sc.hasNext()){ 
      builder.append(sc.next()); 
      builder.append("\n"); 
     } 

     parseRequestFromClient(builder.toString()); 
    } catch (IOException e) { 
     throw new BadRequestException(e.getMessage()); 
    } 
+1

您是否嘗試過任何調試? – xenteros

+0

你確定你正在閱讀你的循環中的任何東西嗎?我沒有看到任何實際上向服務器發送頭的部分是關於什麼類型的請求(它是GET還是別的什麼,你想從服務器獲得哪個資源)。如果沒有這個頭文件服務器,可能只是等待,並不會發送任何可能含有'hasNext()'的東西。 – Pshemo

+0

@xenteros是的,我用Eclipse進行調試。它一直停在'while(sc.hasNext())'這一行。 –

回答

0

你面臨這個問題,因爲hasNext會幕後讀取源,直到源通過返回-1到達終點,以檢查是否有其他的匹配記號的。在這裏並不是你的情況。

作爲提醒這裏是方法hasNext的的Javadoc:

返回true,如果此掃描器的輸入中有另一個標記。這個 方法可能會在等待輸入進行掃描時阻塞。掃描儀不會通過任何輸入前進 。


應該避免重新發明輪子,用一個庫,會爲你做它,就像DavidWebb等等。

+0

感謝分享的帖子。在這種情況下,只使用sc.hasNext()不會讓我消耗http請求的所有內容嗎?現在,我使用'做{ \t \t \t \t nextLine = sc.next(); \t \t \t \t builder.append(nextLine); \t \t \t \t builder.append( 「\ n」); \t \t \t}而(nextLine.equals( 「」)!);'來解決這個問題。 –

+0

您應該考慮使用BufferedReader,而不是https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html –

0

根據rfc 7230(2616已過時)從套接字讀取字節。

Http request必須使用7位usascii進行編碼。 除了0x0a和0x0d以外,任何設置了位7或小於0x20的字節都會導致400錯誤的請求。

直到0x0d讀取0x0a 0x0d 0x0a序列。

之後,第一行是被0x0d 0x0a分開的請求行,其餘是標題行。

將請求行分割爲0x20,它應該返回完全3個部分。 任何其他意味着有人正在盜用你的服務器,發送400狀態。

標題應拼接在「:」給出完全2個部分。其他任何發送400狀態。 修剪(headerkey)!= headerkey 400狀態。

只有在這之後,您纔可以開始urldecode requestline [2]和headervalues。

重複的標題鍵? 400狀態。 重複的請求參數? 400狀態。

做任何事情都會導致一臺服務器比已知的請求參數和/或標題走私可以被破解。

只有通過解釋usascii 7位,你將免疫utf8 hacker 0x0a在usascii 7位中只有一個表示。但幾個在utf8中 0x0a 0x00a 0x000a 0x0000a 0x00000a 0x00000a 0x0000000a是一樣的!

在做任何編程之前閱讀rfc 7230-7235!讓你的服務器非常難以破解。