2012-01-15 45 views
0

我在恢復文件傳輸時出現一個奇怪的現象。Android到電腦FTP恢復上傳奇怪現象

看看下面的圖片,你會看到壞的部分。

這種情況顯然是隨機的,也許每隔10:th。
我通過ftp將我的Android手機中的圖片發送到java服務器。

這是什麼,我忘了這裏。
我看到連接被殺害由於java.net.SocketTimeoutException:
轉移正在恢復這樣

Resume at : 287609 Sending 976 bytes more 

的字節總是正確的,當文件被完全接收。 即使是下面的圖片。

不知道從哪裏開始調試,因爲它的大部分時間工作。

任何建議或想法都將是爐排,我想我完全錯過了這裏的東西。

enter image description here

的裝置發送方碼(僅發送環路):

int count = 1;  
    //Sending N files, looping N times 
    while(count <= max) {   
    String sPath = batchFiles.get(count-1); 

    fis = new FileInputStream(new File(sPath)); 

    int fileSize = bis.available(); 

    out.writeInt(fileSize); // size 

    String nextReply = in.readUTF(); 
    // if the file exist, 
    if(nextReply.equals(Consts.SERVER_give_me_next)){ 
     count++;       
     continue; 
    } 
    long resumeLong = 0; // skip this many bytes 
    int val = 0; 
    buffer = new byte[1024]; 

    if(nextReply.equals(Consts.SERVER_file_exist)){ 
     resumeLong = in.readLong(); 
    } 

    //UPDATE FOR @Justin Breitfeller, Thanks 
    long skiip = bis.skip(resumeLong); 
if(resumeLong != -1){ 
    if(!(resumeLong == skiip)){ 
     Log.d(TAG, "ERROR skip is not the same as resumeLong "); 
     skiip = bis.skip(resumeLong); 
     if(!(resumeLong == skiip)){ 
     Log.d(TAG, "ERROR ABORTING skip is not the same as resumeLong); 
     return; 
     } 
    } 
    } 

    while ((val = bis.read(buffer, 0, 1024)) > 0) { 
     out.write(buffer, 0, val); 
     fileSize -= val; 
      if (fileSize < 1024) { 
      val = (int) fileSize; 
     } 

    } 

    reply = in.readUTF(); 
    if (reply.equals(Consts.SERVER_file_receieved_ok)) { 
     // check if all files are sent 
     if(count == max){ 
      break; 
     } 
    } 
    count++; 



    } 

接收機代碼(非常截斷):

 //receiving N files, looping N times 
    while(count < totalNrOfFiles){ 

     int ii = in.readInt(); // File size 
     fileSize = (long)ii; 

     String filePath = Consts.SERVER_DRIVE + Consts.PTPP_FILETRANSFER; 
     filePath = filePath.concat(theBatch.getFileName(count)); 
     File path = new File(filePath); 
     boolean resume = false; 

     //if the file exist. Skip if done or resume if not 
     if(path.exists()){ 
      if(path.length() == fileSize){ // Does the file has same size 
       logger.info("File size same skipping file:" +       theBatch.getFileName(count)); 
       count++; 
       out.writeUTF(Consts.SERVER_give_me_next); 
       continue; // file is OK don't upload it again 
      }else { 
       // Resume the upload 
       out.writeUTF(Consts.SERVER_file_exist); 
       out.writeLong(path.length()); 
       resume = true; 
       fileSize = fileSize-path.length(); 
       logger.info("Resume at : " + path.length() + 
" Sending "+ fileSize +" bytes more"); 

      } 
     }else 
      out.writeUTF("lets go"); 


     byte[] buffer = new byte[1024]; 
     // *********************************** 
     // RECEIVE FROM PHONE 
     // *********************************** 

     int size = 1024; 
     int val = 0; 

     bos = new BufferedOutputStream(new FileOutputStream(path,resume)); 

     if(fileSize < size){ 
      size = (int) fileSize; 
     } 

     while (fileSize >0) { 
      val = in.read(buffer, 0, size); 
      bos.write(buffer, 0, val); 
      fileSize -= val; 
      if (fileSize < size) 
       size = (int) fileSize; 
     } 
     bos.flush(); 
     bos.close(); 
     out.writeUTF("file received ok"); 

     count++; 

    } 
+0

難道這是因爲我設置長resumeLong = 0;也許它應該是-1 – Erik 2012-01-15 19:23:51

+0

你的代碼可以使用一些評論。嘗試讓發件人放棄每個其他文件的連接,然後看看接收者做了什麼。 – 2012-01-19 15:03:30

+0

這就是我所做的測試。以各種方式殺死連接,但是我不能以這種方式重現它(它發生在它發生時)它就像設備一樣,在發送時,設備代碼BufferedInputStream.skip跳過確定,但仍有一些數字是錯誤的。上傳完成時,文件上的大小總是正確的。我在世界各地使用我的應用程序可能有200個設備,其中一些設備有問題。也許這是某種特定設備搞砸的東西。 – Erik 2012-01-19 19:33:12

回答

2

實測值的誤差和問題是壞邏輯從我的角度來看。 說不了。

我發送的照片在發送前正在調整大小。

的問題是,當恢復失敗的轉移
沒有使用調整大小的圖片後踢,而不是代碼中使用的原
圖爲該有更大的規模大小。

我現在已經建立了一個短暫的高速緩存,用於保存已調整大小的臨時圖片。

鑑於應用程序的複雜性,我簡單地忘記了簡歷期間的文件與原始文件不一樣。

+1

請分享,爲了社區。 – antiduh 2012-01-24 12:19:49

+1

您可能要注意的另一件事是,您沒有檢查skip()是否返回希望跳過的字節數。某些實現可能會返回少於所需的數量(需要另一個電話才能跳過以正確同步您的數據流)。 – 2012-01-24 19:39:59

+0

您的權利,這是一個很好的檢查,以使 – Erik 2012-01-24 19:45:49

2

憑藉的BufferedOutputStream,的BufferedInputStream,您需要注意以下

  1. BuffererdInputStream前
  2. 並刷新剛剛創建後(客戶端和服務器上)創建的BufferedOutputStream。後
  3. 沖洗每次寫(不只是之前關閉)

爲我工作。

編輯

添加sentRequestTime,receivedRequestTime,sentResponseTime,receivedResponseTime你的數據包有效負載。在這些上使用System.nanoTime(),在同一臺主機上運行你的服務器和客戶端,使用ExecutorService爲該服務器運行多個客戶端,並繪製你的(收到發送的)請求和響應數據包, (一些csv格式)。在bufferedIOStream和afterIOStream之前執行此操作。你會很高興知道你的表現提高了100%。讓我非常高興繪製該圖,花了大約45分鐘。

我也聽說使用自定義緩衝區進一步提高了性能。

再次編輯 在我來說,我使用的對象輸入輸出流,我已經添加了4個長變量的有效載荷的對象,並初始化sentRequestTime當我從客戶端發送的數據包,當服務器接收到響應初始化receivedRequestTime,對於從服務器到客戶端的響應也是如此。然後我發現接收和發送時間之間的差異,以找出響應和請求中的延遲。請小心在本地主機上運行此測試。如果您在不同的硬件/設備之間運行它們,它們的實際時差可能會干擾您的測試結果。由於requestReceivedTime在服務器端有時間標記,而requestSentTime在客戶端有時間標記。換句話說,他們自己的當地時間被加蓋(顯然)。這兩款設備在納秒時間內運行完全相同的時間是不可能的。如果您必須至少在不同的設備之間運行它,請確保您有ntp運行(以保持它們的時間同步)。也就是說,你比較bufferedio之前和之後的表現(你真的不關心實際的時間延遲是否正確?),所以時間漂移應該沒有關係。比較緩衝前和緩衝後的一組結果是您的實際興趣。

Enjoy !!!

+0

做了檢查我在哪裏沖洗,並注意到我在一種情況下錯過了它。感謝戰利品 – Erik 2012-01-26 14:08:05

+0

+1在每次寫入之後沖洗(不僅在關閉之前) – Erik 2012-01-27 09:47:28

+0

什麼是receivedResponseTime,任何示例?或我可以閱讀的網頁? – Erik 2012-01-27 20:27:30