我正在学习WCF,LINQ和其他一些技术,从头开始编写自定义远程控制应用程序,如VNC。我正在创建它,主要考虑三个主要目标:
现在我正在使用WCF发送一个表示正在发送的窗口的字节数组:
using (var ms = new MemoryStream()) {
window.GetBitmap().Save(ms, ImageFormat.Jpeg);
frame.Snapshot = ms.ToArray();
}
GetBitmap实施:
var wRectangle = GetRectangle();
var image = new Bitmap(wRectangle.Width, wRectangle.Height);
var gfx = Graphics.FromImage(image);
gfx.CopyFromScreen(wRectangle.Left, wRectangle.Top, 0, 0, wRectangle.Size, CopyPixelOperation.SourceCopy);
return image;
然后通过WCF(TCPBinding,它将始终通过LAN)发送到客户端,并以空白窗口形式重建,没有这样的边框:
using (var ms = new MemoryStream(_currentFrame.Snapshot))
{
BackgroundImage = Image.FromStream(ms);
}
我希望这个过程在CPU和内存使用方面尽可能高效,带宽排在第三位。我的目标是让客户端连接到5台服务器,每台服务器有10多个应用程序。
我现有的方法是最好的方法(在继续使用这些技术的同时),我能做些什么来改进它吗?
我正在研究的想法(但我没有经验):
答案 0 :(得分:21)
你应该知道这一点:
在完成所有这些步骤并对您的最终代码感到满意后,您可以下载VncSharp source code。它实现了the RFB Protocol (Wikipedia entry),"a simple protocol for remote access to graphical user interfaces. Because it works at the framebuffer level it is applicable to all windowing systems and applications, including X11, Windows and Macintosh. RFB is the protocol used in VNC (Virtual Network Computing)."
答案 1 :(得分:4)
看看这个:Large Data and Streaming(WCF)
答案 2 :(得分:4)
我不久前在一个类似的项目上工作过。这是我的一般方法:
一些客户端考虑因素。处理通过WCF服务传输的大量数据时,我发现HttpTransportBinding和XmlDictionaryRenderQuotas的某些参数设置为相当保守的值。所以你会想要增加它们。
答案 3 :(得分:1)
在客户端/服务器之间发送数据的最快方法是发送一个字节数组或几个字节数组。这样,WCF就不必对数据进行任何自定义序列化。
那就是说。您应该使用新的WPF / .Net 3.5库来压缩您的图像,而不是System.Drawing中的图像。 System.Windows.Media.Imaging命名空间中的函数比旧命名空间快,并且仍然可以在winforms中使用。
为了了解压缩是否可行,您必须对方案进行基准测试,以了解压缩/解压缩时间与传输所有未压缩字节的比较。
如果您通过互联网传输数据,那么压缩肯定会有所帮助。在同一台机器或局域网上的组件之间,好处可能不那么明显。
您还可以尝试压缩图像,然后对数据进行分块,并与您在客户端上拼图的块ID异步发送。随着时间的推移,Tcp连接启动缓慢并且带宽增加,因此同时启动两个或四个应该减少总传输时间(所有这些都取决于您发送的数据量)。与在实际图像中执行切片相比,对压缩图像字节进行分块也更容易逻辑化。
总结:与当前代码相比,System.Windows.Media.Imaging应该可以帮助您提高CPU和带宽。记忆明智,我猜是一样的。
答案 4 :(得分:0)
不是捕捉整个图像,而是发送较小的图像子部分。含义:从左上角开始,发送一个10x10像素的图像,然后“移动”十个像素并发送下一个10px的正方形,依此类推。然后,您可以发送数十个小图像,然后在客户端上更新绘制的完整图像。如果您使用RDC在远程计算机上查看图像,您可能已经看到它会进行这种屏幕绘制。
使用较小的图像部分,您也可以分割增量,所以如果当前部分没有任何变化,您可以安全地跳过它,告知客户端您正在跳过它,然后转到下一部分
您肯定希望使用压缩来发送图像。但是,您应该检查是否使用类似于gZip的压缩来获得较小的文件大小,或者如果使用图像编解码器可以获得更好的结果。我从来没有进行过比较,所以我不能以某种方式说出来。
答案 5 :(得分:0)
您的解决方案对我来说很好,但我建议(与其他人一样)您使用磁贴并尽可能压缩流量。另外,我认为你应该一次发送整个图像,只是为了确保客户的增量有一个共同的“基础”。
也许您可以使用现有的流媒体解决方案,例如RTP-H263用于视频流。它工作得很好,它使用压缩,并且有很好的文档和广泛使用。然后,您可以跳过WCF部分并直接转到流部分(通过TCP或UDP)。如果您的解决方案应该投入生产,那么在响应性和网络使用方面,H263流媒体方法可能会更好。
答案 6 :(得分:0)
Bitmap scrImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics scr;
scr.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);
testPictureBox.Image = (Image)scrImg;
我使用此代码捕获我的屏幕。