2013-12-18 72 views
1

我正試圖從客戶端向服務器發送文件。以下是我嘗試過的代碼。但有時,在傳輸過程中會出現數據包丟失。我不確定我錯在哪裏。套接字編程中的數據包丟失java

服務器端代碼:

public static void ReadAndWrite(byte[] aByte, Socket clientSocket, 
      InputStream inputStream, String fileOutput) 
        throws FileNotFoundException, IOException { 
     int bytesRead; 
     FileOutputStream fileOutputStream = null; 
     BufferedOutputStream bufferedOutputStream = null; 
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
     try 
     { 
     fileOutputStream = new FileOutputStream(fileOutput); 
     bufferedOutputStream = new BufferedOutputStream(fileOutputStream); 
     bytesRead = inputStream.read(aByte, 0, aByte.length); 
     System.out.println("The length is "+bytesRead); 
     int count = 0; 
     do { 
      count++; 
      byteArrayOutputStream.write(aByte); 
      bytesRead = inputStream.read(aByte); 
     } while (bytesRead != -1); 
     System.out.println("The count is "+count); 
     System.out.println("The length is "+byteArrayOutputStream.size()); 
     bufferedOutputStream.write(byteArrayOutputStream.toByteArray()); 
     bufferedOutputStream.flush(); 
     bufferedOutputStream.close(); 
     clientSocket.close(); 
     } 
     catch(Exception ex) 
     { 
      Logger.writeLog(ex,Listen.class.getName(), LogType.EXCEPTION); 
      throw ex; 
     } 

客戶端代碼:

public void readByteArrayAndWriteToClientSocket(
      Socket connectionSocket, BufferedOutputStream outToClient, String fileToSend) throws Exception 
    { 
     try{ 
     if (outToClient != null) 
     { 
      File myFile = new File(fileToSend); 
      System.out.println(myFile.length()); 
      byte[] byteArray = new byte[(int) myFile.length()]; 

      FileInputStream fileInputStream = null; 

      try { 
       fileInputStream = new FileInputStream(myFile); 
      } catch (IOException ex) { 
       Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION); 
       throw ex; 
      } 
      BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 

      try { 
       bufferedInputStream.read(byteArray, 0, byteArray.length); 
       outToClient.write(byteArray, 0, byteArray.length); 
       outToClient.flush(); 
       outToClient.close(); 
       connectionSocket.close(); 


       return; 
      } catch (IOException ex) { 
       Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION); 
       throw ex; 
      } 

     } 
     }catch (Exception e) { 
      Logger.writeLog(e, getClass().getName(), LogType.EXCEPTION); 
      throw e; 
     } 
    } 
+0

代碼看起來不錯。如果你不同的文件,他們在哪裏不同? –

+2

「包丟失」是什麼意思?部分數據未收到?沒有收到任何數據?或者像Wireshark一樣檢查數據包顯示數據包被丟棄?在任何有損耗的線路上,偶爾的丟包是不可避免的; TCP的設計考慮到了這一點,並建立了恢復機制以確保交付(如果可能)並確保訂購和完整性。 –

+0

發送文件後,不應該立即關閉'socket'。在終止前等待幾秒鐘。這將確保服務器實際接收文件。 –

回答

3

套接字讀取時,其已獲得了所有你要的字節方法將返回,或者,當它停止接收數據來自網絡。

由於任何真實網絡中的傳輸都經常中斷,因此您需要繼續發出讀取呼叫,直到獲得所需的字節數。

你需要的代碼是這樣的:

 char [] buffer = new char[1024]; 
     int expect = 1000; 
     int sofar = 0; 
     int chars_read; 
     try 
     { 
      while((chars_read = from_server.read(buffer[sofar])) != -1) 
      { 
      sofar = sofar + chars_read; 
      if (sofar >= expected) break; 
      } 
     } 
     catch(IOException e) 
     { 
      to_user.println(e); 
     } 
+0

這裏的關鍵是不要忽略'read'的返回值。 'read(buf,off,len)'不保證它會讀取'len'字節;它可以少讀。無論哪種情況,它都會返回實際讀取的字節數。這適用於從文件讀取和從套接字讀取。 Guava的['ByteStreams.readFully(InputStream,byte [])'](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/io/ByteStreams.html)的行爲方式OP期待'read'工作,雖然'ByteStreams.toByteArray()'更簡單。 –

+0

我如何適應我現有的代碼。我無法理解。 – user3089869

+0

@James:我用你的代碼替換了我的代碼。仍然面臨同樣的問題 – user3089869

3

沒有「丟包」,只是在你的代碼中的錯誤。

的規範辦法複製Java中的流如下:

while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

如果你事先知道的字節數和發送者必須保持連接後傳開,就變成:

while (total < expected && (count = in.read(buffer, 0, expected-total > buffer.length ? buffer.length : (int)(expected-total))) > 0) 
{ 
    out.write(buffer, 0, count); 
    total += count; 
} 

忘記所有的ByteArrayInput/OutputStreams和額外的副本。從文件中讀取併發送到套接字,或者從套接字讀取並寫入文件。