繁体   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