下面的內容是用 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->InitAuthenticateInitAuthenticate的工作是:(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::WinProcClientConnection 類的建立一個線程,線上程中調用了 ClientConnection ::run_undetached 這就相當於該類中的方法是線程方法一樣。 ClientConnection::run_undetached 分析:run_undetached 是假的線程方法()中實現方法可能是:該方法是虛函數,在基類中就已經把該方法作為線程的參數傳給了start 函數,該參數是作為函數指標傳遞的,這樣在Start函數中利用函數指標調用該函數就可以了。繼承類只需把run_undetached當做線程方法實現就行了。
(
這樣做的原因是:
線上程中不允許線程方法作為其成員,編譯不過,是呼叫慣例的問題) 該常式的實現過程:接收伺服器端發送過來的訊息類型: frame 更新,ReadBell 等。然後 switch 進入對應的分。對於 FrameUpdate 的後續處理是:1. 讀取伺服器端更新的Rect數目 RectCount,然後進入for迴圈,次數RectCount2. 讀取每個Rect的頭部資訊,確定這個Rect的座標和寬度和高度,以及編碼資訊3. 根據編碼資訊進入swtich 的特定分支, 接收真正的資料4. 把接收到的 Rect 地區座標轉換成 Windows 座標。