远程桌面控制VC源码剖析

原创
2012/08/08 11:21
阅读数 4.9K

一、引语

    这是个VC6.0的远程桌面控制软件,主要功能是桌面控制、支持多种压缩方式、可调整网格空间数目以及色彩模式选择。源码我也不知道从何而来了,今天整理硬盘无疑间发现的。软件中作者没有留名,很老的一个软件,各种办法也没找到出处,那么就当这个软件是一个开源软件吧。

 

二、结构分析

拿到代码,先看服务器端,RemoteControlServer 文件。

目录结构:(cmd> tree /f |more生成,略有修改)

 E:.RemoteControlServer

│ afiedt.buf

│ .........................

│ ServerWindow.001

│ ServerWindow.dsp

│ ServerWindow.dsw

│ ServerWindow.mak

│ ServerWindow.ncb

│ ServerWindow.opt

│ ServerWindow.plg

│ ........................

└─WndProc.h

  • 目录中有*.dsp、*.dsw文件 ,明显可以看出是vc项目。那么有可能是MFC或者win32/win32 console。
  • 用VS2008打开RemoteControlServer项目,查看类视图,class CMainWnd;只有这一个用户的非继承类,看来不可能是MFC了,倒是很像Win32。
  • 接下来就要先找到WinMain或者main函数了,因为文件没几个,凭着直觉和命名规范,果断在WndProc.cpp找到了WinMain。
  • 因为Win32窗口使用的是消息循环机制,那么直接从WinMain开始看代码了。在WinMain中将回调WndProc函数,OnCreate、OnDestroy、OnKeyDown、OnCommand回根据窗口的消息调用,这样就不难理解程序的结构。
  • 整体的结构可以看图,只是为了整体结构的体现,很多地方进行了省略。图一如既往的烂(第二次使用visio我会说么?)

 

三、网络编程部分

  • MainWnd.cpp (63L) CMainWnd::OnCreate 中,进行Winsock初始化。
  • CMainWnd::OnCommand (160L)中,创建LoadWinsock线程进行通信。
  • Server.c (72L) SelectProtocols函数把一些协议相关的信息放入了pBuf缓冲中,但是pBuf是怎么和套接字关联起来的呢?从头到尾没用过。而且我把SelectProtocols函数调用的那一句注释之后编译,一样能成功链接通信。那这里调用SelectProtocols是怎么起到作用的呢?
  • Server.c (991L) SelectProtocols函数主要主用是:
            1、让所有报文都能到达目的
            2、让所有报文都有序到达
            3、不使用数据报套接字通信
  • SelectProtocols函数中有调用memblast,memblast是用内嵌汇编实现的内存拷贝函数,可能是为了某些平台移植、或者程序编译时不使用平台提供的基本运行时。(感谢BinSys解疑)
  • 为了减小CPU的利用率,禁止在socket上将数据发送到缓冲。设置SO_SNDBUF为0,从而使winsock直接发送数据到客户端,而不是将数据缓冲才发送。(msdn:setsockopt
nZero = 0;
	setsockopt(Listen, SOL_SOCKET, SO_SNDBUF, (char *)&nZero, sizeof(nZero));

  • Server.c (105L) 等待用户连接是一个循环等待并阻塞的过程,并且一直等待用户来连接。
  • 一旦有用户连接到服务器,就会进入新的线程ClientThread;
  • 在ClientThread又用了select模型,只有一个用户,也没有设置超时时间,并且select也不比普通的直接recv阻塞等待快啊。这个真的很难理解。难道是为了程序的拓展性(为多用户或者超时之后做一点别的事么?)
  • 从应用层来分析 协议 ,这个程序使用的是各种“命令”。
                1.REFRESH
                2.WM_系列
                3.RESOLUTION
                4.DISCONNECT

        WM_是一个系列,又分成三个字系列.
                1.鼠标消息
                2.键盘消息
                3.通用消息: 色彩模式,网格数和压缩消息

四、屏幕采集部分

这部分主要是就服务器采集屏幕,然后发送给客户端。

  • 定时采集屏幕发送给用户?不,这样流量的不能接受,而且是没必要的。
  • 采用每次屏幕改变的时候才返回新的屏幕呢?看样子不错,但是还可以优化。
  • 把屏幕划通过网格分成很多小块,每次只发送改变的那些块,这样还不错吧?
    这个程序就是这样设计的,并且也是这个程序设计最巧妙的地方。如果做到最好就是,直接获得变化的那些区域,发送变化的那个区域过去,这个区域很有可能是不规则的。用网格的办法来说,就是网格的每个区域分辨率只有1*1,但是不可能这样做了,要保留所有变化的像素点,不停的遍历对比每一个像素,这样无疑增加是CPU的负担。获得屏幕变化的部分是通过对比位图的出来的(Server.c (683L))。
    MainWnd.cpp (166L) 调用InitDisplay初始化。屏幕刷新是用户提出的请求,当服务器收到刷新屏幕的请求之后,首先获取需要刷新的网格区域,对位图进行压缩获取需要发送的小块,采用压缩发给用户。用户通过解压显示图片。

五、数据压缩

图片之所以需要压缩,是因为捕捉到的屏幕是一块 位图(bitmap)。

  • 色彩的表示是由R、G、B组成, bitmap包含图片每一个像素点的信息(R、G、B分别占8个二进制位,那么R、G、B的的范围恰好是0-255),32位的bmp位图还用了1字节来作为alpha通道,每一个像素点占32位。24位位图俗称“真彩”,因为保留了所有的信息,所以体积很大。
  • 色彩还有另一种表示的方法(jpeg),是灰度、亮度、对比度,因为人眼睛的特殊,这种标准的图片有一定失真,但是肉眼难以判断。简单的说,由于压缩的原因,这种图片每一个像素点RGB值是由周围一些像素点一起决定的。


本程序中压缩采用了:
                1.单遍 霍夫曼编码(Huffman)压缩
                2.多遍霍夫曼压缩编码
                3. Run Length编码(游程编码)
                4.Run Length&Huffman编码

    之前有看过一点计算机图形学, 也做过bmp图片编辑、bmp图片压缩。(秀知识上限了,囧~~~,确实没有好好学过图形学- -#)

六、结束语

    看完服务器端,可以说这个程序涉及的知识面还是很广的。win32、网络编程、c++的oop(很少)、位图压缩、汇编等,把服务器端分析完,基本都能猜到客户端是怎么实现的了。

源码下载及界面截图: http://www.oschina.net/code/snippet_583625_12606

展开阅读全文
打赏
4
27 收藏
分享
加载中
toil博主

引用来自“leehark”的评论

有穿透功能么?等会换PC看一下

木有
2012/08/11 21:04
回复
举报
有穿透功能么?等会换PC看一下
2012/08/11 00:04
回复
举报
toil博主
该评论暂时无法显示,详情咨询 QQ 群:912889742
好,好好学习下
2012/08/09 09:06
回复
举报
该评论暂时无法显示,详情咨询 QQ 群:912889742
更多评论
打赏
5 评论
27 收藏
4
分享
返回顶部
顶部