2015-07-10 52 views
1

我寫了這個簡單的代碼讀取來自TCP服務器數據:TCP讀者失去一些數據

  TcpClient myTcpClient = null; 
     NetworkStream myNetworkStream = null; 

      myTcpClient = new TcpClient(pRemoteIP, pPort); 
      myNetworkStream = myTcpClient.GetStream(); 
      myNetworkStream.ReadTimeout=4000;        


      Byte[] bMesssage = Encoding.UTF8.GetBytes(pMessage);    


      myNetworkStream.Write(bMesssage, 0, bMesssage.Length);    

      Byte[] answer = new Byte[1024]; 
      string sAnswer = ""; 
      int offset = 0;    
      while (true)              
      {     
       myNetworkStream.Read(answer, offset, 1024);     
       sAnswer = Encoding.UTF8.GetString(answer); 
       if (sAnswer.Contains("#END#")) break;       

       Array.Resize(ref answer, answer.Length + 1024);    
       offset += 1024; 
      } 
      int i = sAnswer.IndexOf("#END#"); 
      sAnswer = sAnswer.Substring(0, i); 

      myNetworkStream.Close(); 
      myNetworkStream.Dispose() ; 
      myTcpClient.Close(); 

有時工作很好,而且讀取由服務器發送的數據的大塊,但有時「失去」了一些數據和讓我們說5000個字符而不是25000個字符。

它有什麼問題嗎?

回答

3

您沒有使用返回值myNetworkStream.Read來確定您實際讀取的數據量。它一次可能低至一個字節。

也許應該使用StreamReader來更方便地讀取字符串。使您的協議基於行。

+0

我贊成@usr建議。但是,不使用Read所返回的計數不能解釋損失。相反,RRM可能會獲得大於預期大小的數組。 – Graffito

+0

也許某些API無法處理這可能導致的零字符。我不知道爲什麼會這樣。也許OP只是誤診或代碼丟失。不會是第一次。例如,他的字符串將有多達1023個字符的差距。也許他沒有看到數據,因爲所有的視覺差距。 – usr

1

通常你會保持「緩衝器」在相同的尺寸和積累的答覆,直到你得到你的標記「消息的結束」:

 Byte[] answer = new Byte[1024]; 
     string sAnswer = ""; 
     int bytesRead; 
     MemoryStream ms = new MemoryStream(); 
     while (true) 
     { 
      bytesRead = myNetworkStream.Read(answer, 0, answer.Length); 
      ms.Write(answer, 0, bytesRead); 
      sAnswer = Encoding.UTF8.GetString(ms.ToArray()); 
      if (sAnswer.Contains("#END#")) break; 
     } 
     int i = sAnswer.IndexOf("#END#"); 
     sAnswer = sAnswer.Substring(0, i); 
+0

UTF8不能在任意邊界分割。這將會非確定性地失敗。 – usr

+0

@usr,我很習慣用ASCII來做這件事,我甚至沒有注意到UTF8的部分。以前沒有使用過UTF8,如果你把它存儲在MemoryStream中,就像我上面編輯的那樣,它會更好嗎? –

+0

我認爲這將工作,雖然二次成本。我很高興看到一個不使用ASCII的問題。死,ASCII,死。 – usr