简体   繁体   中英

TCP Packet Sending Error

I'm making a webcam app that sends and receives small images. I have made it be able to send and receive, I tested on 127.0.0.1 and it worked fine, but now I'm using my own external IP address and it seems to send one image, receive one, then mess up, I get some sort of massive integer value in the image size, a minus value which leads it to crash, I think maybe the receive and send are running on their own, and are going out of sync somehow. I put a 1000ms delay before sending out each image and it was slow but working, as soon as I take the delay out, it messes up.

Here is the code :

    // 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;
            }
        }
    }

you need to rethink things a little bit..... the data could arrive in different packets. Your read function will only read what is available. This will lead your system to get out of synch.

I'd build a little protocol for images so I can always tell where the start and end of images are in my data stream.

you don't HAVE to do that, but it makes life easier, you could do it purely by a simple state machine that knows how far through receiving an image it has got. But any non compliance in sending the image ( 1 extra byte in the stream for example) could send the thing out of synch forever.

Read doesn't necessarily read as many bytes as you ask for, just as many happen to be currently available -- you should actually check the return value to see how many it read. The documentation might help give you a better understanding.

You should add logic to keep reading until all of the image bytes have been read. A pseudo-code example:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM