2014-02-28 135 views
1

正嘗試從TcpClient類獲取遠程主機的某些文本。想要遍歷stream.Read,直到我獲得所有數據。如果我使用bytesRead > 0它只是掛起。如果我運行這段代碼,我只能得到遠程主機的第一行輸出,並且程序正常退出。但是,如果我在do循環的第一行中斷,並在調試器中手動逐步執行每次迭代,那麼我最終會得到所有行,就像我期望的那樣。我不明白爲什麼會出現這種情況。這是我使用的代碼:TcpClient不返回所有行

  TcpClient client = new TcpClient("myserver.net", 1234); 
      NetworkStream stream = client.GetStream(); 

      Byte[] buffer = new Byte[256]; 

      StringBuilder sb = new StringBuilder(); 
      int bytesRead; 
      do 
      { 
       bytesRead = stream.Read(buffer, 0, buffer.Length); 
       sb.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead)); 
      } while (bytesRead == 256); 

只是添加,如果我刻意等待額外的時間似乎得到我想要的每一次迭代,但我不明白爲什麼會這樣......

  StringBuilder sb = new StringBuilder(); 
      int bytesRead; 
      do 
      { 
       System.Threading.Thread.Sleep(500); 
       bytesRead = stream.Read(buffer, 0, buffer.Length); 
       sb.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead)); 
      } while (bytesRead == 256); 
+1

使用'StreamReader' – SLaks

+1

'而(bytesRead == 256)'可能是出了什麼問題,因爲網絡流可能不會在發送給您的所有數據一次,它可能應該是'while(bytesRead!= 0)',至少,儘管這是假定Read()塊。 –

+0

另外sb.Append()可能會緩衝數據,這就是爲什麼你看不到它。如果它的Read()塊並且從不返回0,那麼它將永遠阻塞,除非服務器關閉連接。 –

回答

1

它在調試器中工作的原因是因爲您正在減慢代碼以使網絡緩衝區填滿。當您撥打stream.Read並傳入長度爲256(buffer.Length)時,它只是告訴流讀取其緩衝區中的任何內容,直到該長度爲。如果緩衝區中只有100個字節,它將只讀取100個字節,返回值將爲100.這可能是發生了什麼情況(緩衝區沒有可用的完整的256字節),因此您的while條件是否定的更長的滿意和它打破了循環。

考慮到這一點,如果沒有某種協議,「所有數據」不是您可以保證的。數據流本身可能會隨時在緩衝區中出現數據(從您的角度來看)。您需要實現某種長度規範(實質上爲您的消息提供一個頭結構,其中的一部分描述消息的可變長度部分)或某種保留字節或字節序列作爲終結者。然後你就知道要麼讀取特定數量的字節(除非你想拋出異常,否則你不會退出,或者直到遇到終止字節或字節序列時纔讀取)。

1

只需使用StreamReader作爲評論說...

TcpClient client = new TcpClient(); 
client.Connect("myserver.net", 1234); 

var stream = new StreamReader(client.GetStream(),Encoding.ASCII); 
string line = null; 
while ((line = stream.ReadLine()) != null) 
{ 
    Console.WriteLine(line); 
} 
+0

這給了我所期望的所有行,但它似乎阻止了最後一行。我們從來沒有擊中null並逃脫循環。 – user17753

+0

@ user17753當另一端關閉連接時,你會得到什麼?我懷疑另一端永遠不會關閉連接。 – EZI

+0

是的,它必須保持開放。 – user17753