C#尽可能快地通过套接字发送图像

C#尽可能快地通过套接字发送图像,c#,image,sockets,stream,C#,Image,Sockets,Stream,我正在尝试通过试图压缩的套接字发送尽可能快的图像。。。比较图片。。。它仍然工作得很慢。。。 顺便说一句,我试图保存压缩前后的图像,大小是一样的。。。。1或2 kb的内存 查看客户端代码: Bitmap pre; private void Form2_Load(object sender, EventArgs e) { pre = GetDesktopImage(); prev = Compress(ImageToByte(pre)).Le

我正在尝试通过试图压缩的套接字发送尽可能快的图像。。。比较图片。。。它仍然工作得很慢。。。 顺便说一句,我试图保存压缩前后的图像,大小是一样的。。。。1或2 kb的内存

查看客户端代码:

    Bitmap pre;
    private void Form2_Load(object sender, EventArgs e)
    {
        pre = GetDesktopImage();

        prev = Compress(ImageToByte(pre)).Length;
        theThread = new Thread(new ThreadStart(startSend));

        theThread.Start();
    }

    Bitmap curr;
    byte[] compressed;

    private void startSend()
    {
        sck = client.Client;
        s = new NetworkStream(sck);

        while (true)
        {
            curr = GetDesktopImage();

            compressed = Compress(ImageToByte(curr));

            if (Math.Abs(compressed.Length - prev) > 500)
            {
                bFormat.Serialize(s, compressed);

                prev = compressed.Length;
                count++;
            }
        }
    }  
压缩方法:

byte[] Compress(byte[] b)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            using (GZipStream z = new GZipStream(ms, CompressionMode.Compress, true))
                z.Write(b, 0, b.Length);
            return ms.ToArray();
        }
    }

    byte[] ImageToByte(Image img)
    {
        ImageConverter converter = new ImageConverter();
        return (byte[])converter.ConvertTo(img, typeof(byte[]));
    }
这是服务器端:

        while (true)
        {
            try
            {
                bFormat = new BinaryFormatter();

                inBytes = bFormat.Deserialize(stream) as byte[];
                inImage = ByteToImage(Decompress(inBytes));

                theImage.Image = (Image)inImage;
                count++;
                label1.Invoke(new Action(() => label1.Text = count.ToString()));

            }
            catch { }
        }

顺便说一句,我见过一些人使用socket.send,但没有将图像保存到流。。。。你们能解释一下区别吗?请告诉我我的代码中有什么错误,以及如何改进我的算法?

你的问题真的把“过于宽泛”作为一个接近的理由推向了极限。通过网络发送图像数据的一般问题是一个非常广泛的研究领域,有大量不同的技术,具体的应用程序/用户场景决定了哪种技术实际上是最好的

这就是说,有一个非常明显的变化,你可以对你的代码是必要的,这可能会加快它,这取决于瓶颈在哪里

具体来说,您使用
ImageConverter.ConvertTo()
位图
对象转换为
字节[]
,然后使用
gzip流
压缩该字节数组。问题是
ConvertTo()
已经在压缩数据;它返回的
字节[]
包含以PNG格式表示的原始位图,这是一种相当好的图像无损压缩算法

因此,不仅再次压缩它实际上什么也做不了,而且要花费大量的CPU才能做到这一点。不要那样做。只需按原样发送
byte[]
数据,而无需通过
gzip流运行它


现在,所有这些都表明

正如我所提到的,这种改变是否真的能起到这么大的作用取决于其他因素,包括位图有多大,以及您使用的网络有多快。如果你已经用你在问题中发布的低效代码使网络饱和,那么加快代码的速度是没有帮助的

用于处理网络带宽瓶颈的技术包括(但不限于):

  • 使用有损压缩(例如JPEG、MPEG等),从而简单地丢弃发送成本过高的信息
  • 使用差分压缩技术(例如,MPEG、MP4、Quicktime等),该技术利用这样一个事实,即当处理运动图像视频时,从一帧到下一帧的大多数像素不变或至少非常相似
  • 发送渲染命令而不是位图数据。这通常用于VNC或Microsoft的远程桌面/终端服务器API,并利用屏幕上的绘图通常使用相对简单的绘图命令(填充/勾勒矩形、绘制文本、绘制小位图等)影响大量像素这一事实
  • 在许多情况下,这些技术以不同的方式组合在一起以实现最大性能


    如果您想使用这些技术,您需要做的不仅仅是询问有关堆栈溢出的问题。提供这些技术的广泛文档和教程远远超出了本网站的范围。您需要自己研究它们,或者更好地使用现有的实现来实现您的目标。

    什么是
    GetDesktopImage
    ?图像的文件格式是什么?图像有多大?看起来你想做些VNC?不是真的VNC哈哈但是如果你说。。。我使用了捕获图像算法,它比从屏幕上复制图形要快,而且使用的cpu更少。。。我认为它的屏幕截图格式是内存bmp。。。全屏幕大小既然两个图像都是在客户端生成的,为什么不在那里比较它们并将差异发送到服务器呢?它会卸载服务器,特别是在多客户端应用程序中,您有许多客户端向服务器发送屏幕截图。我比较它们,兄弟,然后我只在它们不同的情况下发送图像。。看看代码@Ron Beyer你上面展示的代码没有做任何比较,所以不确定我应该如何认识到这一点?我不是说只在发生变化时才发送图像,我是说只发送图像的变化,这是一组小得多的数据。非常感谢兄弟,我非常感谢你的解释@Peter Duniho,那么关于你所说的
    ImageConverter.ConvertTo()
    我不应该在gzipstream中使用compress方法吗?所以要发送它,只需使用
    compressed=(ImageToByte(curr))?但我注意到如果我也使用压缩,它的kb会更少。。不要问我如何保存这两个文件,有一点不同。。。可能是因为屏幕不同,哈哈,只需使用
    ImageToByte()
    的结果即可。PNG有多种压缩选项,
    ImageConverter
    只使用默认值。因此,您可能会看到数据大小的小幅度减少,再次压缩它,因为您尚未优化PNG压缩。但这些减少不太可能很大(我猜尺寸的改善不到5-10%),而且代价高昂。如果你真的需要的话,你最好得到一个PNG实现,它提供了对压缩的更多控制,并且只优化初始PNG压缩。