2017-06-10 159 views
3

我使用C#爲Windows和Java創建服務器軟件來創建客戶端軟件。 大部分時間都能正常工作,除了那些我不明白的少數例外。TCP發送/接收丟失字節

我通常使用.ReadLine()和.WriteLine()兩端進行通信,除非我嘗試發送二進制數據。那是我直接寫和讀字節的時候。 這是軟件應該如何工作:

  1. 客戶端請求的二進制數據
  2. 服務器響應與二進制數據的長度爲
  3. 客戶端收到的長度,並將其轉換成整數,字符串開始讀(長度)字節
  4. 服務器開始寫(長度)字節

它工作在大多數情況下,但有時客戶端應用程序不會收到完整的數據和b鎖。服務器在寫入數據後總是立即刷新,所以刷新不是問題。

此外我已經注意到這通常發生在較大的文件,小文件(高達〜1 MB)通常不是問題。

注意似乎C#服務器完全發送數據,所以問題很可能在Java代碼的某處。

編輯 - 以下是從客戶端

工作的一些日誌下載pastebin.com/hFd5TvrF

失敗下載pastebin.com/Q3zFWRLB

好像客戶在等待2048個字節最後(在這種情況下應該是length - processed = 2048),但由於某種原因客戶端阻塞。

任何想法我做錯了什麼?下面是服務器和客戶端的源代碼:

C#服務器:

public void Write(BinaryWriter str, byte[] data) 
{ 
    int BUFFER = 2048; 
    int PROCESSED = 0; 
    // WriteString sends the String using a StreamWriter (+ flushing) 
    WriteString(data.Length.ToString()); 
    while (PROCESSED < data.Length) 
    { 
     if (PROCESSED + BUFFER > data.Length) 
      BUFFER = data.Length - PROCESSED; 

     str.Write(data, PROCESSED, BUFFER); 
     str.Flush(); 

     PROCESSED += BUFFER; 
    } 
} 

Java客戶端:

public byte[] ReadBytes(int length){ 
    byte[] buffer = new byte[length]; 
    int PROCESSED = 0; 
    int READBUF = 2048; 
    TOTAL = length; 
    progress.setMax(TOTAL); 
    InputStream m; 
    try { 
     m = clientSocket.getInputStream(); 
     while(PROCESSED < length){ 
      if(PROCESSED + READBUF > length) 
       READBUF = length - PROCESSED; 

      try { 
       PROCESSED += m.read(buffer, PROCESSED, READBUF); 
      } catch (IOException e) { 
      } 
      XPROCESSED = PROCESSED; 
     } 
    } catch (IOException e1) { 
     // Removed because of sensitive data 
    } 

    return decryptData(buffer); 
} 
+0

在Java客戶端中,當您經歷循環時'PROCESSED'的值是多少?我對此感興趣,因爲我很好奇它爲什麼在讀10,000個字節時結束2048個字節。我希望它有1808年閱讀上次通過循環,因爲它在每次迭代中讀取2048字節。 – Poosh

+0

@Poosh 10,000字節是一個例子。我現在不在我的個人電腦上,所以我只能給你估計的價值,我稍後會再次評論準確的價值。 PROCESSED值總是增加1440或2048,最後只增加700。那時候還有2048個字節需要讀取,但正如所說的那樣,它們不會到達客戶端。 – detus

+0

更新:這裏有一些日誌: 工作下載:https://pastebin.com/hFd5TvrF 未能下載:https://pastebin.com/Q3zFWRLB – detus

回答

0

我已經找到了解決。到目前爲止,服務器在發送字節數組後立即發送該長度。出於某種原因,這是行不通的。

所以我已經改變爲:

  1. 發送長度,等待客戶端與 「OK」
  2. 開始寫入字節迴應

不知道爲什麼,但有用。在while(true)循環中運行它,並且它在4分鐘內連續發送數據1000次,沒有問題,所以我想它是固定的。