【问题标题】:Randomly getting Argument Exception and out of memory exception when receiving images via tcp c#通过 tcp c# 接收图像时随机获取参数异常和内存不足异常
【发布时间】:2014-07-23 12:24:44
【问题描述】:

我一直在琢磨为什么会发生这种情况,它会很好地运行几次,但它会随机接收长度为奇数(例如 -123456,或者它会接收为 0) .

然后,当它从流中制作图像时,它不能,因为长度错误。有时长度值看起来像一个正常值,但在生成图像时我仍然会得到参数异常。

编辑:我还随机接收到“len”对象的大量数字,这会导致内存不足异常,但发送方从不发送任何与该数字一样大的东西,所以我不明白该数字的来源来自。

这是接收代码:

    public void ReceiveSS()
    {
        bool firstTimeRun = true;
        TcpListener ssTcpListener = new TcpListener(IPAddress.Any, 63000);
        TcpClient tcpReceiver = new TcpClient();         

            ssTcpListener.Start();
            tcpReceiver = new TcpClient();
            if (!uPnPWorks)
            {
                try
                {
                    Console.WriteLine(contactIP + "      " + port);
                    tcpReceiver.Connect(contactIP.ToString(), port);
                }
                catch (Exception)
                {
                }
            }
            else
            {
                tcpReceiver = ssTcpListener.AcceptTcpClient();
            }
            while (!ssStop)
            {
                try
                {
                    //Start listening for connection.


                    if (tcpReceiver.Connected)
                    {
                        if (firstTimeRun)
                        {
                            //TCP connected. Receive images from contact.
                            NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
                            BinaryReader br = new BinaryReader(receivedNs);
                            byte[] lenOfImage = new byte[4];
                            br.Read(lenOfImage, 0, 4);
                            int len = (int)(lenOfImage[0] << 24) | (int)(lenOfImage[1] << 16) | (int)(lenOfImage[2] << 8) | lenOfImage[3];
                            Console.WriteLine(len);
                            byte[] receivedData = new byte[len];
                            br.Read(receivedData, 0, receivedData.Length);
                            MemoryStream ms = new MemoryStream(receivedData, 0, receivedData.Length);
                            ms.Seek(0, SeekOrigin.Begin);
                            receivedNs.Flush();
                            Bitmap image = new Bitmap(ms);
                            receivedImage = image;

                            //Put image into picturebox.
                            if (this.InvokeRequired)
                            {
                                this.Invoke(new MethodInvoker(delegate() { pboScreenShare.Image = image; }));
                            }
                            else { pboScreenShare.Image = image; }
                            //br.Close();
                            firstTimeRun = false;
                        }
                        else if (!firstTimeRun)
                        {
                            //TCP connected. Receive images from contact.
                            NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
                            BinaryReader br = new BinaryReader(receivedNs);
                            byte[] lenOfImage = new byte[4];
                            br.Read(lenOfImage, 0, 4);
                            int len = (int)(lenOfImage[0] << 24) | (int)(lenOfImage[1] << 16) | (int)(lenOfImage[2] << 8) | lenOfImage[3];

                            try
                            {
                                MemoryStream ms = new MemoryStream();
                                if (len > 0)
                                {
                                    byte[] receivedData = new byte[len];
                                    br.Read(receivedData, 0, receivedData.Length);
                                    ms = new MemoryStream(receivedData, 0, receivedData.Length);
                                    ms.Seek(0, SeekOrigin.Begin);
                                }
                                receivedNs.Flush();
                                receivedImage2 = new Bitmap(ms); //Where I get the random argument exception
                                receivedImage2.MakeTransparent(Color.Pink);
                                Bitmap overlayedImage = new Bitmap(receivedImage.Width, receivedImage.Height);
                                using (Graphics gr = Graphics.FromImage(overlayedImage))
                                {
                                    gr.DrawImage(receivedImage, new Point(0, 0));
                                    gr.DrawImage(receivedImage2, new Point(0, 0));
                                }

                                //Put image into picturebox.
                                this.Invoke(new MethodInvoker(delegate() { pboScreenShare.Image = overlayedImage; }));

                                receivedImage2.Dispose();
                                receivedImage = overlayedImage;
                                //br.Close();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message + "        Getting image");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString() + "     ReceiveSS()");
                }
            }
    }

发送代码:

private void SendSS()
    {
        int cursorX = 0;
        int cursorY = 0;
        TcpListener listener = new TcpListener(IPAddress.Any, 63001);
        listener.Start();
        tcpClient = new TcpClient();
        if (uPnPWorks)
        {
            tcpClient = listener.AcceptTcpClient();
        }
        else
        {

            try
            {
                tcpClient.Connect(contactIP, 63000);
            }
            catch (Exception)
            {
            }
        }
        bool firstTimeRun = true;
        while (!ssStop)
        {
            try
            {
                if (tcpClient.Connected)
                {
                    //Connected. Capture screen image.
                    if (firstTimeRun)
                    {
                        MemoryStream ssmemStream = new MemoryStream();

                        screenShotBMP = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        Bitmap cursorBMP = CaptureCursor(ref cursorX, ref cursorY);
                        Graphics graphics = Graphics.FromImage(screenShotBMP as Image);
                        graphics.CopyFromScreen(0, 0, 0, 0, screenShotBMP.Size);

                        if (cursorBMP != null)
                        {
                            using (Graphics g = Graphics.FromImage(screenShotBMP))
                            {
                                Rectangle r = new Rectangle(cursorX, cursorY, cursorBMP.Width, cursorBMP.Height);
                                g.DrawImage(cursorBMP, r);
                            }
                        }
                        Bitmap saveScreenShot = screenShotBMP;
                        saveScreenShot.Save(ssmemStream, ImageFormat.Png);
                        NetworkStream ns = tcpClient.GetStream();

                        //Convert image to data.
                        BinaryWriter bw = new BinaryWriter(ns);
                        byte[] bytesToSend = ssmemStream.ToArray();
                        byte[] imageLen = new byte[4];
                        int len = bytesToSend.Length;
                        imageLen[0] = (byte)((len & 0xff000000) >> 24);
                        imageLen[1] = (byte)((len & 0x00ff0000) >> 16);
                        imageLen[2] = (byte)((len & 0x0000ff00) >> 8);
                        imageLen[3] = (byte)(len & 0xff);
                        ns.Write(imageLen, 0, 4);
                        ns.Write(bytesToSend, 0, bytesToSend.Length);
                        Console.WriteLine(bytesToSend.Length);
                        ns.Flush();
                        //bw.Close();
                        firstTimeRun = false;
                    }
                    else if (!firstTimeRun)
                    {
                        MemoryStream ssmemStream = new MemoryStream();
                        screenShotBMP2 = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        Bitmap cursorBMP = CaptureCursor(ref cursorX, ref cursorY);
                        Graphics graphics = Graphics.FromImage(screenShotBMP2 as Image);
                        graphics.CopyFromScreen(0, 0, 0, 0, screenShotBMP2.Size);

                        if (cursorBMP != null)
                        {
                            using (Graphics g = Graphics.FromImage(screenShotBMP2))
                            {
                                Rectangle r = new Rectangle(cursorX, cursorY, cursorBMP.Width, cursorBMP.Height);
                                g.DrawImage(cursorBMP, r);
                            }
                        }
                        diffImage = ImageTool.GetDifferenceImage(screenShotBMP, screenShotBMP2, Color.Pink);
                        diffImage.Save(ssmemStream, ImageFormat.Png);

                        try
                        {
                            NetworkStream ns = tcpClient.GetStream();

                            //Convert image to data.
                            BinaryWriter bw = new BinaryWriter(ns);
                            byte[] bytesToSend = ssmemStream.ToArray();
                            byte[] imageLen = new byte[4];
                            int len = bytesToSend.Length;
                            Console.WriteLine(len);
                            imageLen[0] = (byte)((len & 0xff000000) >> 24);
                            imageLen[1] = (byte)((len & 0x00ff0000) >> 16);
                            imageLen[2] = (byte)((len & 0x0000ff00) >> 8);
                            imageLen[3] = (byte)(len & 0xff);
                            ns.Write(imageLen, 0, 4);
                            ns.Write(bytesToSend, 0, bytesToSend.Length);
                            Console.WriteLine(bytesToSend.Length);
                            ns.Flush();
                            //bw.Close();
                        }
                        catch
                        {
                            Console.WriteLine("iox exception");
                        }

                        screenShotBMP = screenShotBMP2;
                    }
                }
            }
            catch (SocketException sockEx)
            {
                Console.WriteLine(sockEx.Message + "        SendSS()");
            }
        }
    }

【问题讨论】:

    标签: c# image tcp argumentexception


    【解决方案1】:

    您假设Read/Receive 准确返回您想要的数据量。事实并非如此。它返回你最多那么多,至少一个字节。调整你的代码来处理这个事实。例如,通过使用BinaryReader 或循环读取,直到获得所需的字节数。

    更好的是:停止使用套接字。使用更高级别的东西,例如 HTTP 或 Web 服务。大多数时候,套接字是错误的解决方案。

    【讨论】:

    • 嗨,我正在使用 BinaryReader,它仍然没有返回适当的数量。我会在你提到的循环中尝试阅读。并使用 http 服务。
    • BinaryReader.Read 只是将调用中继到底层流。但是,ReadBytes 会读取您想要的字节数(如果可用)。
    • 谢谢,BinaryRead.ReadBytes 完美运行!我会投票给你,但我的声誉太低了。 :(
    猜你喜欢
    • 1970-01-01
    • 2012-10-23
    • 2012-01-23
    • 1970-01-01
    • 2016-07-27
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多