下面的内容是用 VC.NET 的调试器调试的整个源码而确定的执行流程. 在分析代码时尽量不要静态的分析代码,这样速度很慢的。利用调试器我们可以通过简单的设置断点来跟踪整个执行流程。
WINVNC
调试其整体流程
在
WinMain
中进行
(1)
初始化套接字库
VSocketSystem
(2)
解析命令行参数
(3)
调用主窗口过程
WinVNCAppMain
WinVNCAppMain
中进行
(1)
确认当前只有一个本实例运行,
vncInstHandler
(2)
创建
Server
类
,
该类的作用:
动态添加和删除客户端
把本地窗口的更新发送给所有连接的客户端
把客户端的鼠标和键盘事件传递给本地
创建套套接字的连接
(3)
创建菜单和托盘图标
vncMenu
vncMenu
中进行:
(1)
构造函数中进行:
创建托盘图标窗口
把窗口托盘图标句柄加入到
vncServer.
m_notifyList
中
初始化
vncProperties->Init
在调用
Init
中
vncProperties->Load
调用
vncProperties ->ApplyUserPrefs
调用
server->SockConnect
完成各种线程的创建和端口邦定工作。
在
Init
中得到密码
检查是否需要验证。
当我们双击图标时
vncProperties->ApplyUserPrefs
会被调用,
vncProperties->ApplyUserPrefs
调用
vncServer::SockConnect
完成可能的程序重新启动。
当有客户端连接时:
当有客户端连接时,
run_undetached
线程接收到连接后
调用
AddClient
把客户端添加到一个客户端的映射数组中
Key
是
ClientSocket
,值是新建的客户端的类
。
然后创建客户端线程
.
把客户端添加到未授权客户端列表
.
客户端线程的工作
(处理与客户端相关的工作):
客户端线程类vncClientThread
的
Run
函数,就相当于线程函数
(
在线程中被调用
)
。
在
vncClientThread->run
函数中调用
vncClientThread::InitVersion()
函数,
InitVersion
函数中工作如下:
(1)
首先向客户端发送自己的
(
服务器方的
)
版本号
(2)
接收客户端的版本号
(3)
验证版本号
客户端线程类vncClientThread
的
Run
函数调用vncClientThread->InitAuthenticate
InitAuthenticate的工作是:
(1)
给客户端发送认证请求
(2)
验证客户端是否合法
vncDesktopThread->run_undetached
线程的工作
(
最核心的功能
)
:
(1)
该线程调用
vncDesktop::Startup()
:
进行所有的初始化工作:
1.
设置象素格式和位图信息
2.
设置各种系统
Hook,
添加系统挂钩,包括屏幕
,
键盘,鼠标。
3.
设置一个定时器来处理拉模式
(polling mode)
,每一秒钟执行一次
.
这样
TriggerUpdate
例程每秒钟被执行一次
.
(2)
设置处理剪切板消息
(3)
创建一个缓存区域对象。所有的区域更新消息都被缓存在该对象中,仅当
TriggerUpdate
被触发时,才把这些消息传给所有的客户端。
认证流程:
1.
版本认证过程:
去掉该版本认证过程。
该版本认证过程:
大致是服务器端
WinVNC
客户端分析
WinMain
à
VNCviewerApp32::NewConnection(
创建
ClientConnection
对象
)
à
ClientConnection::Run
ClientConnection::Run
的功能:
(1)
弹出窗口,接收用户输入的服务器的
IP
地址和端口号
(2)
取得连接信息,进行连接
ClientConnection::GetConnectDetails()
(3)
版本信息的认证
ClientConnection::NegotiateProtocolVersion()
(4)
进行权限的验证
ClientConnection::Authenticate();
修改时间
:
2007
年
8
月
25
日
星期六
修改内容
:去掉了
AuthDialog.cpp
,
AuthDialog.h
,这个认证会话框的内容是客户端输入服务器的密码才能对服务器端进行远程控制。
修改时间
:
8/25/2007 9:43:10 AM
修改内容:
去掉
log.cpp
和
log.h
内容
这个是对各个操作结果内容的记录
对于客户端的代码
该功能实现的一个重要方法:
ClientConnection
类的创建主显示窗口,窗口过程是静态方法
Static ClientConnection::WinProc
ClientConnection
类的创建一个线程,
在线程中调用了
ClientConnection ::run_undetached
这就相当于该类中的方法是线程方法一样。
ClientConnection::run_undetached
分析
:
run_undetached
是假的线程方法
()
中
实现方法可能是:该方法是虚函数,在基类中就已经把该方法作为线程的参数传给了
start
函数,该参数是作为函数指针传递的,这样在
Start
函数中利用函数指针调用该函数就可以了。
继承类只需把
run_undetached
当做线程方法实现就行了。
(
这样做的原因是:
在线程中不允许线程方法作为其成员,编译不过,是调用约定的问题
)
该例程的实现过程:
接收服务器端发送过来的消息类型
: frame
更新,
ReadBell
等。然后
switch
进入对应的分。
对于
FrameUpdate
的后续处理是:
1.
读取服务器端更新的
Rect
数目
RectCount
,然后进入
for
循环
,
次数
RectCount
2.
读取每个
Rect
的头部信息,确定这个
Rect
的坐标和宽度和高度,以及编码信息
3.
根据编码信息进入
swtich
的特定分支
,
接收真正的数据
4.
把接收到的
Rect
区域坐标转换成
Windows
坐标。