2014-03-03 205 views
0

我可能一直盯着這太久,不能看到問題是什麼。Android客戶端/服務器,客戶端沒有收到所有數據

我有一個接受多個客戶端連接並保存套接字的服務器。然後,服務器可以向客戶端發送控制消息來執行任務,除此之外,我想將文件發送到所有連接的客戶端,但客戶端似乎只接收其中的一部分。

出於測試目的,我有一個隨機生成的文本文件69075字節,但儘管它看起來像整個整個文件發送,客戶端只接收高達57000字節左右(變化)。我在服務器應用程序中添加了一個按鈕,可以讓我關閉客戶端套接字,當我這樣做時,客戶端接收到-1,然後是剩餘的缺失文件。

服務器發送文件:

 try { 
     getClientList().get(0).setLocked(true);           
     byte [] mybytearray = new byte [1024]; 

     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile)); 
     OutputStream os = getClientList().get(0).getmSocket().getOutputStream(); 

     Boolean eof = false; 
     int bytesRead; 
     int total = 0; 
     do { 
      bytesRead = bis.read(mybytearray, 0, mybytearray.length); 
      if (bytesRead != -1) {        
       os.write(mybytearray, 0, bytesRead); 
       total += bytesRead;        
       Log.d(TAG_SF, "Total: "+total+" :Sent: "+ bytesRead); 
      } else { 
       eof = true; 
       Log.d(TAG_SF, "EOF, Total sent: " + total); 
      } 
     } while (!eof);       
     os.flush(); 
     bis.close();          
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     getClientList().get(0).setLocked(false); 
    } 

一條消息,該文件之前發送到客戶端的文件名和文件大小是發送和其接收正常。

客戶端接收文件:

 try { 
     int total = 0; 
     byte[] myByteArray = new byte[1024]; 
     int bytesRead; 
     InputStream is = serverSocket.getInputStream(); 
     BufferedOutputStream bos = new BufferedOutputStream(
       new FileOutputStream(path+SD_DIRECTORY+fileName)); 

     do { 
      bytesRead = is.read(myByteArray, 0, myByteArray.length); 
      if (bytesRead != -1){ 
       bos.write(myByteArray, 0, bytesRead);   
       total = total+bytesRead; 
       Log.e(TAG,"Total > "+total+ ": No Bytes : "+bytesRead); 
      } else { 
       Log.e(TAG,"EOF, total received: "+total); 
       break; 
      } 
     } while (total < fileLength); //fileLength and filename are sent before file   
     Log.e(TAG,"Total > "+total+ ": No Bytes : "+bytesRead);    
     bos.flush(); 
     bos.close(); 
     } catch (Exception e) {    
      e.printStackTrace(); 
     } 
+0

看看[這個](http://stackoverflow.com/questions/18583248/sending-png-image-file-from-server-desktop-to-client-android-via-socket-prog/18597338 #18597338)問題,也許它可以幫助你 –

+0

謝謝,同樣的問題與代碼中的例子,所以問題在我的應用程序中的其他地方。請參閱下面的答案 – Scott

回答

0

問題是不是發送和接收的代碼,它工作正常。

我正在向客戶端發送一條消息,首先顯示一個指示要發送文件的控制代碼,然後是文件大小和文件名。然後客戶端等待文件,但服務器在客戶端準備好之前開始發送,並且缺少文件的開頭。

要測試,請在發送文件名併發送文件之前讓服務器線程休眠幾秒鐘,並且工作正常。我可能會讓客戶端向服務器發送'準備好'消息作爲更好的解決方案。

編輯: 雖然這有效,但它不是答案,它似乎與使用緩衝和未緩衝的流有關(請參閱EJP評論)。會做一些相應的重新編寫和更新。不確定SO協議,我應該刪除一個錯誤的答案?

編輯(再次) EJPs評論是絕對正確的,它與打開緩衝輸入流以接收文件名然後在其他地方打開未緩衝的流來傳輸文件有關。我的知識在這個領域(一般來說)是有限的,所以我只是寫了兩個使用相同的非緩衝流。

+1

這不是一個合理的解釋。發送者在發送之前不必等待接收者準備好。數據不會丟失。在網絡代碼中不需要睡覺。您的代碼中必須存在一個錯誤,可能與在緩衝和未緩衝的流之間切換有關。 – EJP

+0

這聽起來更可能,但等待幾秒鐘似乎工作(爲什麼?)。我有一個服務(在客戶端),一旦連接了套接字,就會偵聽傳入的消息。如果傳入消息是文件名和文件大小,它會執行我的問題中的代碼。監聽消息的代碼本質上是 - in = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()); incomingMsg = in.readLine();是否有正確的方法在流之間切換? – Scott

+1

沒有一個正確的方法切換流,不要切換流。在兩端使用相同的流來保證套接字的生命。 – EJP

相關問題