2010-09-01 90 views
2

當我通過TCP連接發送文件時,缺少一些字節。雖然有時文件傳輸已完成。通過TCP連接發送文件時缺少字節

發送方:

class SendFile extends Thread { 

Socket s; 
String toIP; 
String fileName; 
PrintWriter pw; 
BufferedReader br; 
String fromIP; 
String nextHopIP; 
String transferTime; 
int routingIndex; 
final int bufferSize = 65536; 
int readFile; 
byte[] buffer; 
FileInputStream fileIn; 
OutputStream fileOut; 
long fileTransferTime; 

SendFile(String toIP, String fileName) { 
    this.toIP = toIP; 
    this.fileName = fileName; 
} 

public void run() { 
    while (true) { 
     try { 
      fromIP = InetAddress.getLocalHost().getHostAddress(); 
      nextHopIP = Tables.checkRoutingTable(toIP); 

      if (nextHopIP.equals("none")) { 
       System.out.println("Invalid IP address"); 
      } else { 
       s = new Socket(nextHopIP, 3434); 

       fileIn = new FileInputStream(fileName); 
       fileOut = s.getOutputStream(); 
       buffer = new byte[bufferSize]; 
       pw = new PrintWriter(s.getOutputStream()); 
       br = new BufferedReader(new InputStreamReader(s.getInputStream())); 

       pw.println(fromIP); 
       pw.println(toIP); 
       pw.println(fileName.split("\\\\")[fileName.split("\\\\").length - 1]); 
       pw.flush(); 

       //Send file 
       fileTransferTime = System.currentTimeMillis(); 
       int sum = 0; 
       while ((readFile = fileIn.read(buffer)) != -1) { 
        fileOut.write(buffer, 0, readFile); 
        sum += readFile; 
       } 
       System.out.println(sum); 
       fileIn.close(); 
       s.shutdownOutput(); 
       br.readLine(); 
       fileTransferTime = System.currentTimeMillis() - fileTransferTime; 
       System.out.println("File transfer time: " + fileTransferTime + " ms"); 
       s.close(); 
       break; 
      } 

     } catch (IOException ex) { 
      //Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); 
      System.out.println("Connection timed out. Retrying..."); 
     } 
    } 
} 

}

接收方:

class FileTransferThread extends Thread { 

Socket fromSocket; 
Socket toSocket; 
String ip; 
BufferedReader fromBR; 
BufferedReader toBR; 
PrintWriter fromPW; 
PrintWriter toPW; 
String[][] delta; 
String token; 
String toIP; 
String fromIP; 
String nextHopIP; 
String absoluteFileName; 
String fileName; 
int deltaCount; 
int entryCount; 
int socketIndex; 
int i; 
int j; 
int readFile; 
final int bufferSize = 65536; 
byte[] buffer; 
InputStream fileIn; 
FileOutputStream fileOut; 
OutputStream fileHopOut; 
File directory; 
long fileTransferTime; 

FileTransferThread(Socket s) { 
    this.fromSocket = s; 
} 

public void run() { 
    try { 
     ip = InetAddress.getLocalHost().getHostAddress(); 
     fromBR = new BufferedReader(new InputStreamReader(fromSocket.getInputStream())); 
     fromPW = new PrintWriter(fromSocket.getOutputStream()); 
     fromIP = fromBR.readLine(); 
     toIP = fromBR.readLine(); 
     nextHopIP = Tables.checkRoutingTable(toIP); 
     buffer = new byte[bufferSize]; 
     fileIn = fromSocket.getInputStream(); 
     fileName = fromBR.readLine(); 

     if (!fileName.equals("\\send")) { 
      directory = new File("c:\\" + fromIP); 
      directory.mkdirs(); 
      absoluteFileName = "c:\\" + fromIP + "\\" + fileName; 
      fileOut = new FileOutputStream(absoluteFileName); 

      while (true) { 
       try { 
        //if not yet the destination IP, pass to next hop 
        if (!toIP.equals(ip)) { 
         toSocket = new Socket(toIP, 3434); 
         fileHopOut = toSocket.getOutputStream(); 
         toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream())); 
         toPW = new PrintWriter(toSocket.getOutputStream()); 
         toPW.println(fromIP); 
         toPW.println(toIP); 
         toPW.println(fileName); 
         toPW.flush(); 

         //Send file 
         while ((readFile = fileIn.read(buffer)) != -1) { 
          fileHopOut.write(buffer, 0, readFile); 
         } 
         toSocket.shutdownOutput(); 
         fromPW.println(toBR.readLine()); 
         fromPW.flush(); 
         toSocket.close(); 
        } else { 
         int sum = 0; 
         while ((readFile = fileIn.read(buffer)) != -1) { 
          fileOut.write(buffer, 0, readFile); 
          sum += readFile; 
         } 
         System.out.println(sum); 
         fileOut.flush(); 
         fileOut.close(); 
         fromPW.println("1"); 
         fromPW.flush(); 
        } 
        fromSocket.close(); 
        break; 
       } catch (IOException ex) { 
        //Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex); 
        System.out.println("Connection timed out. Retrying..."); 
       } 
      } 
     } else { 
      while(true) { 
       try { 
        //if not yet the destination IP, pass to next hop 
        if (!toIP.equals(ip)) { 
         toSocket = new Socket(toIP, 3434); 
         fileHopOut = toSocket.getOutputStream(); 
         toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream())); 
         toPW = new PrintWriter(toSocket.getOutputStream()); 
         toPW.println(fromIP); 
         toPW.println(toIP); 
         toPW.println(fileName); 
         toPW.flush(); 
         //Send file 
         while ((readFile = fileIn.read(buffer)) != -1) { 
          fileHopOut.write(buffer, 0, readFile); 
         } 
         toSocket.shutdownOutput(); 
         fromPW.println(toBR.readLine()); 
         fromPW.flush(); 
         toSocket.close(); 
        } else { 
         while ((readFile = fileIn.read(buffer)) != -1) { 
         } 
         fromPW.println("1"); 
         fromPW.flush(); 
        } 
        fromSocket.close(); 
        break; 
       } 
       catch (IOException ex) { 
        //Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex); 
        System.out.println("Connection timed out. Retrying..."); 
       } 
      } 
     } 
     fromSocket.close(); 
    } catch (IOException ex) { 
     Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

}

+2

你能給出一個發送方和接收方數據丟失了多少字節的例子嗎?我想知道是否是回車(\ r \ n)類型的問題? – CoolBeans 2010-09-01 22:03:51

+0

缺失的字節範圍從1kb到20kb。我不認爲它是一個回車問題,因爲有次同一個文件傳輸成功。 – 2010-09-02 04:09:00

+0

缺失的字節總是在最後? (即它是否被提前截斷?) – caf 2010-09-02 04:58:41

回答

0

注意socket.getInputStream規定,可能發生利用這一設施的種類的數據丟失。特別是:

網絡軟件可能丟棄由套接字緩衝的字節 。

+0

我認爲這適用於緩衝流。這也適用於OutputStream嗎?我的印象是OutputStream不會緩衝數據,因此我的代碼中沒有flush語句。雖然我嘗試在循環後添加一個flush語句,但仍然還有字節丟失。 – 2010-09-02 04:08:36

1

您不關閉 - 因此不刷新 - 稱爲fileout的SocketOutputStream。 (你真的應該考慮更少誤導性的名字......)。

嗯...它似乎shutdownOutput做到這一點;它的javadoc寫道:

禁用此套接字的輸出流。 對於TCP套接字,任何先前寫入的數據將被髮送 ,然後是TCP的正常連接終止序列。

如果您在套接字上調用 shutdownOutput()後寫入套接字輸出流,則該流將拋出 IOException。

我離開這個以防其他人有同樣的想法。

+0

fileOut在接收端是一個OutputStream對象。 來自javadocs:OutputStream的flush方法什麼都不做。 – 2010-09-02 03:57:02

0

發現錯誤。看來BufferedReader正在獲取應該用於該文件的大量數據。