TCP数据包发送错误

本文关键字:错误 数据包 TCP | 更新日期: 2023-09-27 18:20:07

我正在制作一个发送和接收小图像的网络摄像头应用程序。我已经使它能够发送和接收,我在127.0.0.1上进行了测试,它运行良好,但现在我使用自己的外部IP地址,它似乎发送一个图像,接收一个,然后出错,我在图像大小中得到了某种巨大的整数值,一个导致它崩溃的负值,我认为接收和发送可能是独立运行的,并且不知何故会不同步。在发送每张图像之前,我设置了1000毫秒的延迟,虽然速度很慢,但可以工作,我一取消延迟,它就一团糟。

这是代码:

    // This sends.
    private void NewFrameReceived(object sender, NewFrameEventArgs e)
    {
        Bitmap img = (Bitmap)e.Frame.Clone();
        byte[] imgBytes = EncodeToJpeg(img, 25).ToArray();
        if (_tcpOut.Connected)
        {
            NetworkStream ns = _tcpOut.GetStream();
            if (ns.CanWrite)
            {
                System.Threading.Thread.Sleep(500);
                ns.Write(BitConverter.GetBytes(imgBytes.Length), 0, 4);
                ns.Write(imgBytes, 0, imgBytes.Length);
            }
        }
    }
    // This receives.
    private void listeningThread_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        // start listening for connections
        _tcpIn = new TcpListener(IPAddress.Any, 54321);
        _tcpIn.Start();
        TcpClient _inClient = _tcpIn.AcceptTcpClient();
        while (true)
        {
            NetworkStream ns = _inClient.GetStream();
            if (ns.CanRead && ns.DataAvailable)
            {
                Byte[] imgSizeBytes = new Byte[4];
                ns.Read(imgSizeBytes, 0, 4);
                int imgSize = BitConverter.ToInt32(imgSizeBytes, 0);
                Byte[] imgBytes = new Byte[imgSize];  <-- ERROR, GET CRAZY LARGE VALUE
                ns.Read(imgBytes, 0, imgSize);
                MemoryStream ms = new MemoryStream(imgBytes);
                Image img = Image.FromStream(ms);
                picVideo.Image = img;
            }
        }
    }

TCP数据包发送错误

您需要重新思考一下。。。。。数据可以以不同的分组到达。您的读取功能将只读取可用的内容。这将导致您的系统失去同步。

我会为图像建立一个小协议,这样我就可以随时知道图像的开始和结束在我的数据流中的位置。

你不必这么做,但这会让生活变得更轻松,你可以完全通过一个简单的状态机来实现,它知道通过接收图像它已经走了多远。但是,任何不遵守发送图像的行为(例如,流中多出1个字节)都可能导致图像永远不同步。

Read不一定能读取您要求的那么多字节,就像当前碰巧有多少字节一样——您实际上应该检查返回值,看看它读取了多少字节。文档可能有助于您更好地理解。

您应该添加逻辑以保持读取,直到读取完所有图像字节。伪代码示例:

total_bytes_read = 0;
while (total_bytes_read != total_bytes_needed)
{
    bytes_left_to_read = total_bytes_needed - total_bytes_read;
    total_bytes_read += read(buffer, total_bytes_read, bytes_left_to_read);
}