簡體   English   中英

C# TcpClient 從流中讀取或獲取不完整的數據

[英]C# TcpClient reading or getting incomplete data from stream

我有一個模擬視頻流的 exe。 我連接到它並偶爾讀取預期的數據,但通常我只得到前 28 個字節,然后是 65508 個字節的零。 假設視頻流工作正常。

TcpClient tcpClient = new TcpClient ();

int port = 13000;
myIP = IPAddress.Loopback.ToString();

tcpClient.Connect (myIP, port);
NetworkStream netStream = tcpClient.GetStream ();

byte[] bytes = new byte[tcpClient.ReceiveBufferSize];

netStream.Read (bytes, 0, (int)tcpClient.ReceiveBufferSize);

string dataString = Encoding.ASCII.GetString (bytes);

Console.WriteLine("\ndataString: "+dataString.Substring(0,1000));
Console.WriteLine("\nnumber of bytes read: "+bytes.Length); 

tcpClient.Close ();
// Closing the tcpClient instance does not close the network stream.
netStream.Close();

我怎樣才能做到這樣我每次都能得到預期的輸出?

TCP 表示(雙向)數據流。 您應該在循環中繼續讀取它,並根據需要解析數據。 它沒有消息的概念 - 一側的十次寫入可以導致另一側的一次讀取,就像一側的一次寫入可以導致另一側的十次讀取一樣容易。

您與 TCP 的合同如下:

  • 如果接收緩沖區中有數據, Read立即返回,用盡可能多的可用數據填充您提供的緩沖區,直至緩沖區的長度。 讀取的字節數是Read的返回值。
  • 如果接收緩沖區中沒有數據, Read將阻塞,直到至少有一個字節的數據。 然后按照第一種情況進行。
  • 如果對方關閉套接字, Read將返回零。

所以為了讓 TCP 工作,你需要一個循環。 您如何准確地形成循環取決於您要嘗試做什么。 如果你真的在處理邏輯上是流的數據(例如音頻數據),只要盡可能快地閱讀並處理你獲得的任何數據。如果你需要發送消息,你需要實現一個消息協議。 如果您需要一次性消息,您可以繼續閱讀,直到Read返回零。

您的情況可以使用第一種方法處理 - 繼續閱讀直到流關閉,然后將接收到的數據向前推送。 假設數據實際上是一個 UTF8 文本流,基本的接收器看起來像這樣:

using (var client = new TcpClient())
{
  tcpClient.Connect(myIP, port);

  var stream = client.GetStream();
  var buffer = new byte[4096]; // Adapt the size based on what you want to do with the data
  var charBuffer = new char[4096];
  var decoder = Encoding.UTF8.GetDecoder();

  int bytesRead;
  while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
  {
    var expectedChars = decoder.GetCharCount(buffer, 0, bytesRead);
    if (charBuffer.Length < expectedChars) charBuffer = new char[expectedChars];

    var charCount = decoder.GetChars(buffer, 0, bytesRead, charBuffer, 0);
    Console.Write(new string(charBuffer, 0, charCount));
  }

  client.Close();
}

請注意,這不會進行錯誤處理,因此不要在任何生產代碼中使用它。 如果您期望多個同時連接,您可能還想使用Async方法。 這只是為了說明處理通過 TCP 接收的數據流的基本方式。

如果您想更深入地了解如何處理 TCP,我在https://github.com/Luaancz/Networking 上有一些非常簡單的示例。 我還沒有找到任何關於 C# 的好的教程或代碼示例,所以如果這還不夠,您可能需要深入研究有關套接字、TCP 和所有這些的文檔。

或者只是使用現有的網絡庫,而不是嘗試編寫自己的 :) TCP 仍然非常低級。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM