【问题标题】:length header suddenly has wrong value when use read int32?使用读取 int32 时,长度标头突然出现错误值?
【发布时间】:2017-08-29 18:12:59
【问题描述】:

我写了一个tcp监听器来接收来自单个客户端的一系列图像,这是服务器的代码:

new Thread(() =>
{
  while (true)
  {
    displayingFrame.Start(); // another thread to display images
    Socket socket = listener.AcceptSocket();
    TcpClient client = new TcpClient();
    client.Client = socket;
    Debug.WriteLine("Connection accepted.");

    var childSocketThread = new Thread(() =>
    {
      NetworkStream ns = client.GetStream();
      BinaryReader br = new BinaryReader(ns);

      while (true)
      {
        using (MemoryStream ms = new MemoryStream())
        {
            int length = br.ReadInt32();

            Debug.WriteLine("length : " + length);

            byte[] buf = new byte[1024];
            int totalReaded = 0;
            int readed = 0;
            while (totalReaded < length)
            {
                readed = br.Read(buf, 0, buf.Length);
                ms.Write(buf, 0, readed);
                totalReaded += readed;
            }

            byte[] frame = ms.ToArray();
            this.frames.Enqueue(frame);
            Debug.WriteLine("frame enqueued with length " + frame.Length);

        }
      }
    });
    childSocketThread.Start();
  }
}).Start();

它很好地接收帧,但突然br.ReadInt32(); 返回一个非常大的长度,因此br.Read(buf, 0, buf.Length); 需要很长时间写入内存流并且它在帧内写入了错误的数据。

这是客户:

TcpClient client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Loopback, 20000));
NetworkStream ns = client.GetStream();
BinaryWriter bw = new BinaryWriter(ns);
while ( true )
{
    byte[] frame = Screenshot();

    bw.Write(frame.Length);
    Console.WriteLine("a frame length has flushed : " + frame.Length);

    bw.Write(frame);
    Console.WriteLine("a frame itself has flushed");
}

Console.ReadKey();

这里是调试信息:

【问题讨论】:

    标签: c# networking io


    【解决方案1】:

    如果你检查你得到的十六进制值 - 1196314761 - 你会得到 0x474E5089 最后转换成 ASCII 你会得到 GNP\x89 这给了我们已知的魔法值 \x89PNG 这是标记PNG 文件。您实际上是在读取屏幕截图的内容作为长度。

    确保您用于读取数据的代码不会从前一帧读取太多数据。我认为您用于读取数据的代码不包括您可能会在一个.Read 中获得 2 帧内容的事实,但稍后您就不会关心您是否有太多数据。你只检查它是否不小于长度。

    【讨论】:

    • 非常感谢,,, 好像是在读取帧数据而不是长度,这是因为我没有检查缓冲区是否适合数据,代码现在运行良好
    猜你喜欢
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    • 2013-07-12
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多