首页 > 代码库 > 再来一篇装逼老文章:屏幕传输算法

再来一篇装逼老文章:屏幕传输算法

仍然是以前写的一篇老文章,从其它站点拷贝回来的。此文写于07年,思想幼稚,特别是后期说教味道特别严重,仅供参考。另外,从Vista后,实际上操作系统已经在应用层提供了一个类似Mirro的接口,程序员已经没必要再自己进行变化判断了。
============================================

引用页:http://hi.baidu.com/cxmlqkoyadbekqd/item/4f3a361bdf32d28d89a9561b

老陈—为什么黑洞远程控制的屏幕传输算法是世界第一的

http://www.138soft.com/html/tip/1/26.htm

文档名称:老陈—为什么黑洞远程控制的屏幕传输算法是世界第一的
文档类别:Delphi编程文章
文档作者:老陈
发布日期:2007-04-29
文档备注:藏鲸阁
查看次数: 243

为什么黑洞远程控制的屏幕传输算法是世界第一的

        << 黑洞远程控制>>(http://www.138soft.org/)是一款老牌的免费国产远程控制软件,而且跟同类产品不一样,每个新版本都是以创新为目的,以实质行动推动着中国远程控制的进步.它的屏幕传输速度是目前没有使用虚拟屏幕驱动的情况下世界最快的.

        首先来解释一下标题,为什么说”世界第一”.如果要承认黑洞的屏幕传输速度是世界第一的,那么必须首先承认Radmin是最快的(逻辑命题:1:Radmin是世界第一快.2:黑洞比Radmin快.3:所以黑洞是世界第一).Remote Administrator(http://www.radmin.com/)是俄罗斯一个公司写的一款远程控制软件,现在最新版本是3.0版本,使用了虚拟屏幕驱动技术.而3.0之前的版本是直接GDI操作的(NT4下可以使用驱动).我们先来看其官方公布的一组数据:

一:Radmin和Real VNC 4.0的比较(http://www.radmin.com/products/comparisons/index.php)

1
2
3
Tests *                          Radmin 2.2     Real VNC 4.0
Beziers Screen Saver refresh
test details...                  337            1

其官方数据显示,在启动贝尔曲线屏幕保护的情况下,Radmin 2.2比Real VNC 4.0 快337倍.

二:Radmin和其它同类产品的比较(http://www.radmin.com/products/comparisons/radmin_vs_netop_and_others.php)

1
2
3
4
5
6
7
8
9
Program name            FPS (Frames Per Second)
                       Area size 32x32      Area size 64x64
RADMIN2.2                    60,6           53,6
NetOp Remote Control 8.0     24,8           66,6
Remote Desktop               34,9           10,0
Remote Assistance            38,2           10,0
PcAnywhere 10.5              3,85           12,5
RealVNC 4.1.1                0,19           0,19
Dameware 4.9.0.4             1,65           1,66

三:Radmin和Laplink Gold的比较(http://www.radmin.com/products/comparisons/laplink.php)

1
2
3
Tests *                           Radmin 2.1 Laplink Gold 11
Dragging an icon over desktop     150          1
Window minimized/maximized        2            1

        这些数据足以表明Radmin Administrator是目前世界上屏幕传输速度最快的软件.而在相同网络环境和机器条件下,黑洞的屏幕传输速度比它快,所以才有了本文的标题:为什么黑洞远程控制的屏幕传输算法是世界第一的.
        下面我们再来说一下为什么黑洞远程控制的屏幕传输速度那么快.
        实际上,屏幕传输的速度由几个方面决定:抓取、压缩和网络传输.而压缩和网络传输目前没有什么能突破的地方.例如压缩,压缩的一般原理是把大量相同的数据用很小的数据来表示.比如说,有一组数据 A A A A A A A A A A C,那么可以直接把前面十个A用$表示.这就是压缩的实质.一般压缩算法分为字典压缩和树压缩.字典的意思是,例如前面说的,遇到$,就去查字典,然后还原出10个A.字典还可以分为动态字典和固定字典.还可以分为是否直接在压缩文件内部带字典.而树压缩就是我们大学里面学的例如二叉树之类了,有点类似BMP位图和矢量图的,一幅图片,可以完全用点和颜色来表示每个象素(位图一般是这种格式),但是如果放大了该图片,就会变得模糊了.矢量图则类似用一段公式来绘制一幅图片.这样一来,即使放大或缩小,都不会失真.实际上,我上面这些关于压缩的解说并不是官方的标准解释,所以请科班出身的程序员不必深究,毕竟我只是一个自学考试毕业的专科生,理论不够扎实.上面的说法只是根据我个人实际接触的一些压缩算法从而得到的结论.
        屏幕压缩一般不会使用字典压缩算法(因为目前字典算法并不特别针对BMP图片,而且字典本身也有一定体积),目前比较流行的算法其实还是树算法,而树算法实质是数学运算,数学运算则是考验CPU的东西了.所以为什么我们压缩文件的时候CPU占用率很高的缘故.
        再来讨论网络传输.网络传输实质上能优化的东西也不会太多.毕竟大家一般都是使用相同的Winsock库.另外,假设本身网络速度只有56KB,你再优化也不可能大于56KB/S的速度.
        所以,屏幕传输唯一能突破的地方是抓取部分.而核心就是只发送变化部分.实际上,判断屏幕变化速度最快的肯定是虚拟显卡驱动(NT下用mirro driver,9x下用DDI HOOK).它工作于显示器输出和显示卡之间,屏幕还没有输出的时候,它已经拦截到了.感兴趣的朋友可以参考DDK带的例子代码(假设你的DDK默认安装在C盘,那么该例子位于C:NTDDKsrcvideodisplaysmirror目录下).
        在应用层如何快速判断屏幕变化的部分呢?我们在黑洞2002就曾经尝试过极速传输屏幕.具体原理是先抓取第一幅,然后后面每一幅跟前面的比较,然后只发送变化部分.具体代码可以从我们的主页http://www.138soft.com/下载.不过该例子尚有很多需要值得优化的地方,例如数据分流压缩从而降低CPU占用等.
        实质上,每次整屏抓取效率是非常低的.我们的目的是什么?是为了判断变化部分而已.所以,只需要优化判断算法即可.而算法是很多的,例如,随机取点,假设一个8X8的区域,随机取其中一个点,如果它变化了,那么就把该区域当作已经变化了即可.这种算法实质上处理的好会比Radmin的速度更加快.而黑洞使用的是类似于Radmin的算法,就是逐行扫描.但是作了更多的优化.
        由于我本身不懂反汇编,而且Radmin本身算法加密的很厉害,所以无法从反汇编的角度来分析证实.但是我们可以使用另外的方法来证实.我们先用Delphi来写一个HOOK,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
library HookGDI;
 
{$IMAGEBASE $58800000}
 
uses
Windows, madCodeHook;
 
const
strHookHostFile: string = ‘R_server.exe‘;
var
    BitBltNext: function(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC;
      XSrc, YSrc: Integer; Rop: DWORD): BOOL; stdcall;
 
function BitBltCallback(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC;
    XSrc, YSrc: Integer; Rop: DWORD): BOOL; stdcall;
var
    CallFile: string;
begin
    Result := BitBltNext(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, Rop);
    CallFile:= GetModuleFileName(0);
    if Pos(strHookHostFile, CallFile) > 0 then
    begin
      TracTxt(Format(‘%s:(Dest:%d,x:%d,y:%d,Width:%d,Height:%d,SrcDC:%d,XSrc:%d,YSrc:%d,Rop:%d)‘,
        [‘BitBlt‘, DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, Rop])+#$D#$A,‘BitBlt‘); 
      end;
end;
 
begin
    HookAPI(‘gdi32.dll‘, ‘BitBlt‘, @BitBltCallback, @BitBltNext);
end.

这个程序很简单,就是HOOK了BitBlt函数,当R_server.exe调用该函数的时候,就将各参数打印出来.下面是我们得到的一组数据(800X600分辨率下):
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:0,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:1,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:2,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:3,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:4,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:5,Rop:13369376)
BitBlt:(Dest:-1023343793,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:6,Rop:13369376)
……………………………………………………………………………………
BitBlt:(Dest:503382584,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:8,Rop:13369376)
BitBlt:(Dest:503382584,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:28,Rop:13369376)
……………………………………………………………………………………
BitBlt:(Dest:1359020403,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:18,Rop:13369376)
BitBlt:(Dest:1359020403,x:0,y:0,Width:800,Height:1,SrcDC:1426129579,XSrc:0,YSrc:38,Rop:13369376)

        从上面数据可以看出,Radmin的算法实质是先从第一行开始逐行扫描,然后每间隔10行再扫描.周而复始.这么做的作用是什么?就是为了判断变化部分.如果某行发生变化了,那么记录下来,扫描完毕后,结合所有变化的行,计算并返回变化的区域即可.
找到了方向,接下来就简单了,写代码就OK了.而代码只是体力劳动,这里就不再作描述了.
        可能还是会有人问,这样一来,最多只能达到和Radmin一样的速度,而且还得保证你判断的算法和Radmin一样.因为逐行扫描只是方向性问题.你凭什么说黑洞比Radmin快?这个问题问的好.实质上,在屏幕小区域发生变化的情况下,我们仍然无法达到和它一样的速度.大屏幕变化下也只是接近了它的速度.后来我们使用了两个优化的技巧.第一个技巧就是位图颜色.黑洞屏幕传输拥有自主研发算法.比起传统算法,最明显的是客户端在Windows2000操作系统下,如果抓取的服务端屏幕桌面背景设置为空白桌面,而且传输时使用256色,则传输过来的图像会稍微失色.但是这种格式比起Radmin和传统的位图格式,数据会减少1/3.从而导致传输速度大大提高.第二个技巧就是扫描,实质上,Windows下的窗口大都是矩形,所以,扫描的时候,如果扫描到标题(例如,你打开计算器,出现矩形),那么下面部分肯定是变化了的.所以应该直接从当前坐标往下扫描,从而马上得到变化区域.而使用上面的分析方法,可以看到Radmin永远是一成不变的扫描.
        我们在2006年6月1日就已经完成此算法的开发,当时也在138放了一个和radmin比较的演示录像和软件.同时申请了计算机软件著作权申请证书(登记号2006SR11163).扫描复印件见http://www.138soft.org/BlackHole/arithmetic.htm.是国内最早实现此功能的软件.但是,必须指出的是,这一算法如果没有站在巨人radmin的身上,那么实现时间或许要迟到很多.虽然整个算法与radmin没有实际关系,但是它的实现给我们信心,在GDI层次也可以达到非常快的速度.
        最后请容许我说几句牢骚话.
        第一就是基础很重要.很多人整天说学校教的东西没有用处,很落后.其实是错误的.万丈高楼平地起.算法是程序的灵魂.很难想象一个高中生,没有接触过数据结构之类,能写出效率多高的东西.或许拼凑组装一下代码还行.要写出高效稳定的程序,基础是非常非常重要的.否则你到了一定程度,就无法再突破了.我已经毕业工作大概有三年时间,在学校的时候就已经写过很多免费软件.但是毕业后仍然花了一年多时间再重新学习数据结构.即使今天到书店,我仍然喜欢看类似数学奥林匹克题集的东西,而对于具体技术实现的,反而基本没有买过书籍.所幸我高中读的文科,给了我极大的理解能力.
        第二就是国内对知识产权保护的意识非常薄弱.国内做共享软件的应该都知道,如果你的软件做的好,绝对不用三天时间,就会出现注册机,破解是合法的.我曾经在一个破解论坛看到,有一个残废人,通过努力自学,终于写出了一个共享软件,但是很快就被破解了,他在那个破解论坛恳求大家不要破解他的软件,因为他的生活来源就是注册费.其实这也是为什么中国软件技术一直没有自己的核心技术的原因.干的再好,马上被破解,或者被反编译.干与不干一个样,长此以往,又有谁还去研究技术?都去学破解和反汇编了.有人说,反汇编和破解有利于技术进步,俄罗斯当年就是靠这个赶上美国的.实际上,俄罗斯是因为抓教育才赶上美国的,而不是所谓的破解.这个看每年的国际数学奥林匹克获奖者就知道了(中国也不错,只可惜的是,一般那些天才清华毕业后就出国为其它国家效力了,反而是一些平时学习不怎么样的经常被老师歧视的留下来为国家死心塌地的奉献).就拿radmin来说,你觉得他是靠反汇编取的现在的成绩的吗?凡是创新的东西,都不可能靠破解,破解反而容易造成依赖性.这也是我一直没有深入研究反汇编的原因.人都是有惰性的,很多时候,人都是逼出来的.如果有相同的东西了,你还会自己去研究么?反出来就是.对于这点,我是深有体会的.我以前读书的时候,数学成绩其实不是很突出.每次都是70~80分左右,在那个省一级学校实在属于下游水平.但是每个数学老师都特别喜欢我,为什么?很简单,我从不认真听课.每次考试前,就背公式,然后上考场,解题都是临场发挥.结果老师看到解题的方法和他讲的不一样(数学有时侯是变相考记忆,记熟每种题型的解法,然后考试,这也是应试教育的弊端),以为我是学有余力的情况下还有创新.例如,两个分数比较大小,传统办法是先把分母化成一样,然后分子大的分数就大.而我直接用分子和分母交叉相乘,如果A的分子乘以B的分母,比B的分子乘以A的分母大,那么A肯定大于B.反之亦然.实际上,我是被逼的,我也很想用老师教的解体方法去解,但是我没听课.实质上,做软件也是一样.有时侯,你看别人的东西看的多,做出来的反而没有自己的特色了.
        也有人说,国内的实际情况决定了不能抓的太严,否则很多家庭连电脑都用不上,所以注定这一代的程序员是被牺牲的一代,到下一代就好了.我们记得,比尔.盖茨当年访问中国的时候,就惊呼:我就不明白,为什么人们肯花三千元去买彩色电视机,却不可能花几百元买操作系统.实际上,今天几万元一平方的房子人们都买的起,又怎么可能注册不起一个几十块的软件.就拿远程控制软件来说,我们做了四年的免费软件,我们对此有很深切的感受.做正规的远程控制,不可能有人买.很简单,破解的PcAnyWhere之类多的是,有必要再花几十块注册你的么?中国从来不缺少天才,只是缺少强迫他们去研究的环境.所以天才都喜欢走捷径去搞破解,最后仅有的天赋慢慢也消失了.天赋有时侯是一个悲哀,因为天才大都能找到偷懒的捷径.而无论在哪个行业,要想成为一个真正伟大的人,仅有天赋是不行的.这也是为什么小聪明的人多,成功的人少的缘故.
        第三个就是对开源的一些看法.我经常看到很多程序论坛上面,一有人发表什么东西,后面肯定跟着一大帮人叫贴代码的.很早以前,程序员是很贵的,后来IBM培养了一大批,最后变成15元能请一大打.直到今天,仍然鼓吹什么开源,搞开源社区(实质是利用程序员的免费劳动来对抗微软).人家开源是因为一个月工资抵你一年,饱才能思淫欲啊.有时侯真的想不明白,凭什么一个人辛苦研究的东西,非要无偿奉献出来.然后懂了再反过来说您落后了.你不开源还被叼.如果一个东西大家都懂,你需要月薪1万,他只需要3K.而你懂的他都懂(虽然你是刻苦研究出来的,他是花三分钟看了你的开源懂的),你觉得老板会请谁呢?所以每次看到那些人一边在那里潇洒的贴代码,另外一边在那里痛骂老板无良压制工资,其实这不是自己搬石头砸自己的脚?都是自己造成的.商人的本质是利益作为唯一目的,而程序员自己的利益需要自己去争取.当然,我们并不反对开源,实际上,我们早期一直公开过很多代码和技巧,虽然现在看来有些过时,但是在当时绝对是最新的.我们只是希望不要那么浮燥,别人是否开源是别人的事情,别人也没有义务和责任一定要开.如果你整天就跑到论坛上说:我要实现XXXX,请给出代码.那么你永远不可能进步.而且建议,别人在工作时间帮你完成本来属于你的工作,你应该把工资交给他.
        最后就是对一些所谓”黑客”的看法了.如果大家有留意,其实2003年~2004年可以说是中国安全研究的顶峰时期,百花齐放.各路大侠、各种技巧层出不穷.再看看今天,到处是XX培训班,而培训内容却一直停留在2004年,各大网站贴的也是过时的发霉的技巧.新的东西少之又少.如果一个东西和金钱挂钩,则一切都变质了.没有交流就没有进步,但是如果一个东西能卖钱,你觉得还会有人交流么?即使他不爱钱,他不拿去卖,也会收起来,绝对不会让自己的东西变成别人手里的赚钱工具.而且,也没听说培训出什么高手来,现在和以前的高手前辈们也没听说谁是通过参加培训后变成的.真正好学的人,自然会去找资料和研究.不好学的,你拿着枪逼他也没用.
        忠言,都是逆耳的.良药也大都苦口.中庸之道可以用于待人接物.适合社会科学.但是绝对不适合自然科学.更加不适合于IT实作行业.否则所取的成绩也是”中庸”的.希望这篇文章提到的技巧让更多的屏幕传输类软件达到国际水平,也希望这篇文章发的牢骚能让祖国的IT界明天发展的更好!

再来一篇装逼老文章:屏幕传输算法