2010-12-07 74 views
0

我正在開發一個應用程序,通過套接字與第三方應用程序進行通信。基本上,我的應用程序需要發送一些請求到服務器,並且服務器返回一些數據。當服務器向我發回少量數據時,一切正常。但是,當我從服務器請求大量數據時,我的應用程序有時不會收到完整的數據,並且會間歇性地發生。Java Socket讀取大量數據時遇到間歇性錯誤

我在互聯網上做了一些研究,並遵循了我發現的套接字編程示例,但仍然無法解決問題。以下是我目前的實施。

 BufferedInputStream is = new BufferedInputStream(socket.getInputStream()); 

    //I know the size of data that I am expecting from the server 
    byte[] buffer = new byte[length]; 

    int count = 0; 
    int current = 0; 

    while(count < length) { 
     current = is.read(buffer, count, length - count); 

     if(current == -1) { 
      break; 
     } else {     
      count += current; 
     }   
    } 

我知道我期望從服務器獲得的數據大小。發生問題時,read()方法在從服務器完全接收數據之前返回-1。我沒有任何訪問服務器端的實現。請告訴我,如果我錯過了我的代碼中的任何內容,或者有更好的方法去做。

回答

1

你的代碼看起來基本健全。 (使用BufferedInputStream在這種情況下不會提高性能,如果有的話,它會使速度變慢,但這不太可能導致此問題。)

也可能在內存中緩存大量內容客戶端導致客戶端無響應足夠長的時間導致套接字超時。但是,如果你的文件大小隻有幾兆字節,你可能會打折這種可能性。

但是,我懷疑真正的問題是客戶端或服務器端的套接字超時太小。但是,如果您無法訪問服務器端配置和日誌,則很難診斷此問題。

3

如果read方法返回-1,則服務器在發送它發送的任何內容後關閉套接字。期。如果你期待更多的數據,你錯了。

服務器可能是錯誤編碼的,例如,關閉其套接字而不是最外面的輸出流,從而丟失數據。或者可能您的結尾不正確,例如,通過爲每個套接字創建多個BufferedInputStreams,而不是一個套接字的生命週期。

您的代碼只是複製DataInputStream.readFully()。但是你真正應該做的是處理每個緩衝區的負載,而不是試圖在內存中創建一個任意大的緩衝區。這隻會浪費空間並增加延遲。

+0

謝謝!我在整個套接字的生命週期中只使用一個BufferedInputStreams。所以我可能必須檢查服務器端。 – 2010-12-07 10:03:53

+0

對於你提到最後一段關於「處理收到的每個緩衝區負載」的問題,我不是很清楚。你能解釋一下嗎?非常感謝EJP。 – 2010-12-07 10:11:41

+0

當您讀取少量數據時,BufferedInputStream很有用,例如一次只能讀取一個字節,當一次讀取就能夠一次獲得更多數據。即它可以在操作系統的一次大型讀取中使成千上萬的小讀取成爲可能。然而,在你的情況下,最大讀取大小比緩衝區大,並且大於你要讀取的典型數據包大小。即它的正上方 – 2010-12-07 10:42:34

0

有自己的代碼中一些嚴重的問題:

假設長度= 8GB

你會得到很多的創造這樣規模的一個byte []的問題。

int count 
int current 

這應該是

long count 
long current 

,但如果你這樣做,代碼將不再編譯。所以你有一個Integer.MAX_VALUE的最大文件大小。如果你將你的下載存儲到一個bytearray中。 (感謝EJP)

你必須將這些數據寫入到除RAM之外的其他內存中。對於32位JVM,您絕不會創建比〜1,3 GB更大的字節。