2012-05-21 95 views
0

我正在寫下載程序。我只想用java Socket來請求一個文件。所以我按照HTTP協議規則在我的套接字中編寫。我的應用程序創建連接並在讀取標題後,使用我的套接字的InputStreamread()方法。一切順利。有時連接可能會丟失。但是我存儲了我正在讀取的哪個字節,因此它再次創建一個具有HTTP遠程GET的新Socket並繼續其工作。但是,當下載即將完成時,我的意思是當少於10 KB時,所有連接都將丟失,並再次(按計劃)嘗試打開新的套接字並繼續工作。它完全讀取響應的標題,但在讀取正文的任何​​字節之前,read()方法返回-1並再次嘗試打開一個新的套接字和read()其餘字節,但問題仍然存在。重點是每次響應標題可以完全讀取。並且我看到Content-Length:響應頭字段正好是文件的其餘字節。我忘了提及:我的代碼有一個問題,因爲我檢查了很多服務器上的許多文件,結果是一樣的。這裏是代碼:Java Socket InputStream read()總是返回-1,結束之前

// Some fields: 
int state; 
long start, current, end; 

// in a thread: 
while (state != FINISHED) { 
    if (state == DOWNLOADING) { 
     try { 
      // fill a new socket with Ranged GET [current, end] 
      Socket s = initConnection(); 
      InputStream in = s.getInputStream(); 
      int readNo = 0; 
      FileOutputStream out = getTempFile(); 
      byte[] buffer = new byte[1024]; 
      // read response headers successfully and prints them, request range is OK. a sample of its print is at the end of page 
      readHeaders(in); 
      while (state == DOWNLOADING && (readNo = in.read(buffer)) != -1) {      
       current += readNo; 
       out.write(buffer, 0, readNo); 
      } 
      if (readNo == -1) { 
       // at nearly end of download always print this and values never changes, where usually they have 3000 byte difference 
       System.out.println("**************> (" + current + " - " + end + ")"); 
      } 
      if (currentByte == endByte) { 
       state = FINISHED; 
       //mergeParts(); 
       // code never reaches here 
       dlInfo.checkAllPartsFinished(); 
      } 
      out.flush(); 
      out.close(); 
      s.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      state = ERROR; 
      error = e.getMessage(); 
      errorRetry++; 
     } 
    } else if (state == PAUSED) { 
     // ... 
    } else ... 
    } 
} 

在文件的結尾那裏沒有什麼變化的響應頭的一個示例:

HTTP/1.1 206 Partial Content 
Date: Mon, 21 May 2012 14:34:27 GMT 
Server: Apache 
Last-Modified: Sat, 21 Apr 2012 02:16:20 GMT 
ETag: "4006d32e-f691e0-4be26fda00500" 
Accept-Ranges: bytes 
Content-Length: 7859 
Content-Range: bytes 2012041-2019899/16159200 
Connection: close 
Content-Type: application/octet-stream 

**************> (2012041 - 2019899) 

我不知道是什麼問題,但不管是什麼,它發生在近流的結束。 我花了很多時間花了很多時間,我完全困惑。我會很感激任何幫助!

感謝名單

+0

Whad有'readHeaders'嗎?你確定它沒有閱讀更多的信息嗎?它使用某種緩衝區嗎? –

+0

在'readHeaders'中,我從套接字輸入流中創建了一個'BufferedReader'並且完全讀取到body。如果它不是確切的,它會在控制檯中打印一些內容! – MHM

+2

@MHM:那就是你的問題!一個'BufferedReader'將**讀入一個緩衝區**,從中可以獲取內容。這意味着當'readHeaders'返回時,比標題更多的**將被從'InputStream'中讀取。這意味着你缺少的數據是*在開始處*,而不是在末尾。 –

回答

2

你在你readHeaders()方法上的InputStream上層疊緩衝的閱讀器/流?我的猜測是你正在這樣做,而且這個緩衝流正在讀取比你期望的更多的InputStream(因爲它是緩衝的)。這些字節然後從readHeaders()方法返回時丟失。

更新:

剛剛看到您的最新評論。這正是你的問題。 BufferedReader佔用了主體字節的一部分。

+0

謝謝隊友,你有東西,讓我檢查一下! – MHM

+1

正確讀取頭文件是在Java中實現HTTP協議最棘手的部分之一。 –

+1

提示:最好讀入一個字節數組並找到'\ r \ n \ r \ n'(CR LF CR LF)序列(和空行),然後將*之前的部分*轉換爲'字符串「(這是你的標題),以及*之後的所有* *是數據的開頭*。 –