【问题标题】:How can I show the received image using C#?如何使用 C# 显示接收到的图像?
【发布时间】:2017-08-29 07:07:26
【问题描述】:

我同时拥有 C# 应用程序和 C++ 应用程序。在 C++ 应用程序中,我将桌面屏幕捕获为 BITMAP,并通过 TCP 套接字将图像发送到 C# 应用程序。我可以通过 TCP 发送捕获的图像,但无法在 C# 应用程序中显示接收到的图像。请看代码:

在 C++ 应用程序中,用于发送图像的代码 (How can I convert BITMAPINFOHEADER into Byte array using c++):

send(theSocket, (char*)&bi, sizeof(bi), 0); send(theSocket, lpbitmap, dwBmpSize, 0);

在 C# 应用程序中:

private void startListening()
    {
        int port = 0;
        port = Convert.ToInt32(textBox1.Text.ToString());

        Console.WriteLine("Server is starting...");
        byte[] data = new byte[1024];
        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);

        Socket newsock = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);

        newsock.Bind(ipep);
        newsock.Listen(10);
        label1.Invoke((MethodInvoker)delegate
        {
            label1.Visible = true;
            label1.Text = "Waiting for a client...";
        });


        Socket client = newsock.Accept();
        IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;

        label1.Invoke((MethodInvoker)delegate
        {
            label1.Text = "Connected to client. Recieving image...";
        });

        try
        {
            while (true)
            {
                data = ReceiveVarData(client);

                using (MemoryStream ms = new MemoryStream(data))
                {

                    bytesRead = ms.Read(data, 0, data.Length);
                    if (bytesRead > 0)
                    {
                        try
                        {
                            Image img = Image.FromStream(ms);
                            pictureBox1.Invoke((MethodInvoker)delegate
                            {
                                pictureBox1.Image = img;
                                pictureBox1.Refresh();
                            });
                        }
                        catch (ArgumentException e)
                        {
                            Console.WriteLine("something broke");
                        }
                    }
                }

                if (data.Length == 0)
                    newsock.Listen(10);
            }
        }
        catch (Exception)
        {
            this.Invoke((MethodInvoker)delegate
            {
                this.Close();
            });
        }

        client.Close();
        newsock.Close();
    }


 private byte[] ReceiveVarData(Socket client)
    {
        int total = 0;
        int recv;
        byte[] datasize = new byte[4];
        byte[] data=null;
        try
        {
            recv = client.Receive(datasize, 0, 4, 0);
            int size = BitConverter.ToInt32(datasize, 0);
            int dataleft = size;
            data = new byte[size];
            while (total < size)
            {
                recv = client.Receive(data, total, dataleft, 0);
                if (recv == 0)
                {
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Client disconnected.");
            this.Invoke((MethodInvoker)delegate
            {
                this.Close();
            });
        }
        return data;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var t = new Thread(startListening);
        t.IsBackground = true;
        t.Start();
    }

【问题讨论】:

  • 您是否通过调试器查看发生了什么?
  • 在将接收到的数据转换为图像时,在这行代码“Image img = Image.FromStream(ms);”上出现异常'Parameter is not valid'
  • 把它和你的调试器告诉你的任何其他东西/任何与问题有关的东西一起放在问题中。

标签: c# c++ sockets tcp


【解决方案1】:

.NET 不会从流中读取 BITMAPINFOHEADER。它期望流数据匹配正常的文件格式,但BITMAPINFOHEADER 严格来说是一种内存格式。您需要在流中包含 BITMAPFILEHEADER(紧接在 BITMAPINFOHEADER 之前),才能成功呈现 .NET 能够处理的 BMP 文件格式流。

也就是说,如果您可以提供帮助,我不建议您这样做。通过将图像数据编码为众所周知的文件格式(例如 PNG 或 JPEG)来压缩图像数据会更好。这将解决编码问题,同时显着减少您传输的数据量(从而改善传输延迟)。大概在您的 C++ 端,您可以访问一些可以为您生成 PNG 或 JPEG 数据的图像处理库。

【讨论】:

  • 检查在 C++ 应用程序中添加 BITMAPFILEHEADER,现在代码如下: 'send(theSocket, (char*)&bfh, sizeof(bfh), 0); // BITMAPFILEHEADER send(theSocket, (char*)&bi, sizeof(bi), 0); // BITMAPINFOHEADER send(theSocket, lpbitmap, dwBmpSize, 0); // 来自位图的“位”缓冲区。不过,同样的例外正在发生,知道吗?
  • @JithinJose:没有好的minimal reproducible example,没有想法。我确实注意到您的接收代码似乎需要一个 int 长度前缀,您没有提到发送。并且接收代码在尝试处理它之前并没有验证它是否实际读取了所需的 4 个字节(对于这种用法,最好使用BinaryReader)。有很多方法可以解决这个问题,而只有一种方法可以解决这个问题。因此,即使我指出了您分享的信息中的缺陷,您也没有分享足够多的信息来了解是否所有这些缺陷都是已知的。
  • 请从dropbox.com/s/c4t0trywwma9p7h/RemoteScreenProjects.zip?dl=0 下载我的服务器应用程序 (C#) 和客户端应用程序 (C++) 的示例项目,并提供您的反馈。
  • @Jithin:恐怕你误解了 Stack Overflow 模型。所有帮助都是在志愿者的基础上提供的,期望请求帮助的人将在 Stack Overflow 站点本身上提供所有必要的信息,并将所有代码限制为一个好的minimal reproducible example,发布在他们的问题中。根据您在问题中提供的信息,我上面的回答就足够了。但是,如果您可以改进上述问题以使其符合这些标准,我很乐意看看。另请参阅How to Ask,并确保您阅读了该页面末尾链接的文章。
  • 我认为问题出在接收端。因为客户端是这样发送图像的:'send(theSocket, (char*)&bfh, sizeof(bfh), 0);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 2011-12-18
相关资源
最近更新 更多