2012-11-15 102 views
1

我對客戶機服務器映像傳輸有奇怪的行爲。目前,當服務器從緩衝區中讀取32768個字節時總是停頓,總文件大小爲36556字節。 while循環不會結束,但它不會打印其中的任何打印語句,也不會拋出異常。我已經嘗試了幾種不同大小的字節緩衝區,甚至比圖像大小還要大,並不能解決問題。通過TCP連接傳輸圖像時遇到問題

客戶端代碼:

private static void writePhoto(Socket socket) throws IOException { 

    OutputStream outputStream = new BufferedOutputStream(socket.getOutputStream()); 

    String file_path = "E:\\Eclipse\\Workspace\\DNI_PsuedoClient\\" + 
      "src\\main\\resources\\BuckyBadger.jpg"; 
    try { 
     InputStream stream = new FileInputStream(file_path); 
     System.out.println(stream.available()); 
     try { 
      byte[] buffer = new byte[1024]; 
      int readData; 
      int i = 1; 
      while((readData=stream.read(buffer))!=-1){ 
       System.out.println(readData + " " + i); 
      outputStream.write(buffer,0,readData); 
      i++; 
      } 
      System.out.println("done writing to buffer"); 
     }catch (IOException e) { 
       System.err.println("File Error"); 
       e.printStackTrace(); 
       System.exit(-1); 
     }finally { 
      stream.close(); 
     } 
    } finally { 
    } 
} 

服務器代碼

private static java.io.File createFile(Socket client) throws IOException { 

    System.out.println("Starting to create file"); 
    InputStream stream = new BufferedInputStream(client.getInputStream()); 

    System.out.println("1"); 
    // Create file from the inputStream 
    java.io.File Recieved_File = new java.io.File(thread_ID + ".jpg"); 
    System.out.println(thread_ID + ".jpg"); 
    System.out.println("2"); 

    try { 
     OutputStream outputStream = new FileOutputStream(Recieved_File); 
     System.out.println("3"); 

     try { 
      byte[] buffer = new byte[1024]; 
      System.out.println("4"); 
      int readData; 
      int i = 1; 

      while ((readData = stream.read(buffer)) != -1) { 
       System.out.println("start"); 
       outputStream.write(buffer, 0, readData); 
       System.out.println(readData + " " + i + " " + (i * readData)); 
       i++; 
       System.out.println("end while loop"); 
      } 
     } finally { 
     System.out.println("5"); 
     outputStream.close(); 
     System.out.println("6"); 
     } 
    } finally { 
    } 
    System.out.println("Created file"); 
    return Recieved_File; 
    } 

正如你可以看到我已經使用打印語句中的服務器代碼,試圖找出問題的幾點嘗試。任何見解都會非常有幫助。

爲了進一步的參考,我已經有了完全相同的服務器代碼,用於與Windows手機進行交互,手機在該手機上拍照並將其上傳到服務器。我現在將代碼更改爲在多個線程上運行,並使用模擬交互的Java客戶端首先在Java中進行測試。 Java客戶端正試圖將存儲在驅動器上的照片發送到服務器。客戶端看起來正常工作,因爲它將整張照片放入緩衝區。

我寫了一個協議,那就是:

public DNI_Protocol(Socket socket, String threadID) { 
    client = socket; 
    thread_ID = threadID; 
    } 

public String processInput(String theInput) { 

String theOutput = null; 
if (state == WAITING) { 
    System.out.println(theInput); 
    if (theInput.equals("Upload")) { 
    state = UPLOAD_PHOTO; 
    theOutput = "Send Photo"; 
    } else if (theInput == "View") { 
    state = VIEW; 
    theOutput = "Send Request"; 
    } else { 
    theOutput = "Waiting"; 
    } 
} else if (state == UPLOAD_PHOTO) { 
    // if (theInput != "Sending Photo") { 
    // TODO: Throw a state exception with a message 
    // return "exit"; 
    // } 
    setupDrive(); 
    try { 
    Image_Handle = createFile(client); 
    System.out.println("Uploading file"); 
    uploadedFile = Drive_Interface.uploadFile(false, Image_Handle, drive); 
    System.out.println("file Uploaded"); 
    google_ID = uploadedFile.getId(); 
    System.out.println(google_ID); 
    Image_Handle.delete(); // We are done with the file so we can delete it 
    System.out.println("deleted file"); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    } 
    theOutput = "Send Keywords"; 
    state = UPLOAD_KEYWORDS; 
} else if (state == UPLOAD_KEYWORDS) { 
    if (theInput != "Sending Keywords") { 
    // TODO: Throw a state exception with a message 
    return "exit"; 
    } 
    // TODO: Add code to get keyword arraylist and upload information to 
    // the database 
    theOutput = "exit"; 
} 
return theOutput; 

}

+2

你期待什麼發生?您的代碼無法讓客戶端停止服務器繼續等待更多數據。所以服務器一直在等待。 (當您設計用於在這兩個程序之間進行通信的協議時,您應該回答的兩個問題是「客戶端如何告訴服務器它具有整個文件?」以及「服務器如何知道它具有整個文件?「)也許你打算關閉客戶端的連接? –

+0

你是否曾嘗試調用'flush()',使用'Buffered'相關流的所有實例?由於我對「文件處理」不太熟悉,因此我只能提供一個小想法來看看。 –

+0

@GagandeepBali沒有明確的緩衝,所以唯一的緩衝是Nagle的算法,它不會引入很長的延遲。 –

回答

0
 int sum = 0; 
     while ((readData = stream.read(buffer)) != -1, && sum < 36556) { 
     System.out.println("start"); 
     outputStream.write(buffer, 0, readData); 
     System.out.println(readData + " " + i + " " + (i * readData)); 
     i++; 
     sum = sum + readData; 
     System.out.println("end while loop"); 
    } 

該代碼在32768字節的完全相同的位置停頓;

+0

最有可能的是,以前的代碼已經讀取了一部分36,556字節,所以這段代碼會一直等待。您必須確保在此之前讀取內容的代碼不會讀取單個額外的數據字節 - 否則此代碼將永久等待。記錄這個循環接收到的前幾個字節,我打賭你會發現它們是進入文件的一種方式。 –

3

你的服務器代碼這樣說:

 while ((readData = stream.read(buffer)) != -1) { 
      System.out.println("start"); 
      outputStream.write(buffer, 0, readData); 
      System.out.println(readData + " " + i + " " + (i * readData)); 
      i++; 
      System.out.println("end while loop"); 
     } 

這使得從套接字讀取直到套接字關閉或服務器出現錯誤,沒有其他原因read將返回-1。由於這些條件都不會發生,服務器將停留在此循環中。你根本沒有寫任何代碼來處理文件的末尾。

如果服務器知道它將讀取特定數量的字節,則它在讀取該字節數時需要跳出while循環。如果客戶端要通過關閉套接字或關閉TCP連接的一個方向告訴服務器它已完成發送文件,則客戶端需要代碼來完成此操作。否則,服務器將永遠等待。

+0

如果while循環保持無限期運行,由於「開始」和「結束while循環」打印語句一遍又一遍地重複,因此可以分辨出來。這不會發生。我已經添加了服務器的代碼,以期望36556字節的文件大小,並在達到這一點後繼續前進。事情是它從來沒有達到這一點,它停止在32768字節,正如我已經多次說過,並且什麼都不做。 – JME

+0

進一步重複我的觀點。如果我將字節數組大小更改爲4096,並且將代碼設置爲期望36556字節的數據,則while循環仍然停留在32768字節。我想解釋的是,代碼不會崩潰,但它也不會給我任何重複的陳述表示無限循環。你的解決方案解決了我沒有跡象表明的無限循環。 – JME

+0

它不會退出循環,你還需要什麼? –