2011-06-29 25 views
0

服務器端代碼Socket編程:InputStream的滯留在環路 - 閱讀()始終返回0

public static boolean sendFile() { 
     int start = Integer.parseInt(startAndEnd[0]) - 1; 
     int end = Integer.parseInt(startAndEnd[1]) - 1; 
     int size = (end - start) + 1; 

     try { 
      bos = new BufferedOutputStream(initSocket.getOutputStream()); 
      bos.write(byteArr,start,size); 
      bos.flush(); 
      bos.close(); 
      initSocket.close(); 
      System.out.println("Send file to : " + initSocket); 
     } catch (IOException e) { 
      System.out.println(e.getLocalizedMessage()); 
      disconnected(); 
      return false; 
     } 

     return true; 
    } 

客戶端

public boolean receiveFile() { 
     int current = 0; 

     try { 
      int bytesRead = bis.read(byteArr,0,byteArr.length); 
      System.out.println("Receive file from : " + client); 
      current = bytesRead; 
      do { 
       bytesRead = 
       bis.read(byteArr, current, (byteArr.length-current)); 
       if(bytesRead >= 0) current += bytesRead; 
      } while(bytesRead != -1); 
      bis.close(); 
      bos.write(byteArr, 0 , current); 
      bos.flush(); 
      bos.close(); 
     } catch (IOException e) { 
      System.out.println(e.getLocalizedMessage()); 
      disconnected(); 
      return false; 
     } 
     return true; 

    } 

客戶端是多線程的,服務器端不使用多線程。我只是粘貼一些代碼,如果你想看到所有的代碼,請告訴我。

在我調試代碼後,我發現如果將max線程設置爲any,那麼第一個線程總是停留在此循環中。​​總是返回0.雖然,服務器已關閉流,它不會退出循環。我不知道爲什麼......但另一個線程正常工作。

do { 
    bytesRead = 
    bis.read(byteArr, current, (byteArr.length-current)); 
    if(bytesRead >= 0) current += bytesRead; 
} while(bytesRead != -1); 
+2

好的T恤。 :P –

回答

2

您的輸入文件(您發送的文件?)有多大?「byteArr」有多大? 此外,通過時間的檢查有多少字節讀取,你已經叫bis.read(..)兩次:

int bytesRead = bis.read(byteArr,0,byteArr.length); 

你可能想讀/發送大文件比你的緩衝,所以你可能想做這樣的事情:

 byte [] buffer = new byte[4096]; 
     int bytesRead; 
     int totalLength = 0; 

     while(-1 != (bytesRead = is.read(buffer))) { 
      bos.write(buffer, 0, bytesRead); 
      totalLength += bytesRead; 
     } 
     bos.close(); 
     is.close(); 

「is」將是一個普通的InputStream,彼得是正確的,你不需要緩衝它。

+0

它的工作原理!謝謝 ! –

+0

我有一個問題。 爲什麼設置緩衝區大小等於4096?其他數字不比這個好嗎? –

+0

你幾乎可以在這裏使用任何數字,4k是(或者現在是)內存中的默認頁面大小,所以分配更少的空間是沒有意義的,因爲操作系統無論如何都分配了4k。 – PhilW

2

當您給它一個沒有剩餘空間的緩衝區時,read()將返回0。 (這似乎是這裏的情況)

我會建議你使用DataInputStream.readFully()這樣做給你。

dis.readFully(byteArr); // keeps reading until the byte[] is full. 

如果您只寫大字節[]或只寫入一段數據,則使用緩衝流只會增加開銷。你不需要它。

順便說一句:當你調用close()時,它會爲你調用flush()。

+0

它與第一個線程一起工作,它不會卡住,但另一個線程捕獲java.io.EOFException。 'dis.readFully(byteArr); bis.close(); bos.write(byteArr); bos.flush(); bos.close();' –

+0

在哪個語句上?你想在關閉它後寫信給'bos'嗎? –

+0

它會在此行上引發異常'dis.readFully(byteArr);'帶有線程n> 1。 –