• 沒有找到結果。

2.1 遠端桌面程式介紹 遠端桌面程式介紹 遠端桌面程式介紹 遠端桌面程式介紹

2.1.3 X Window

X Window 系統(也常稱為 X11 或 X)是一種以點陣圖方式顯示的視窗系統 [3]。最初是 1984 年麻省理工學院的研究,之後變成 UNIX、Linux 等作業系統 所一致適用的標準化軟體工具套件及顯示架構的運作協定,經過二十多年的演 進,現今已成為工業標準。X Window 與一般的作業系統不同,在設計時就是以 Client/Server 為理念,整個 X Window 可以分為幾個部份:X Server、X Client、

X Protocol 和 X Library。

● X Server:負責控制顯示卡將影像畫在顯示器上,並且管理鍵盤和滑鼠的 事件,產生視窗、對應視窗及刪除視窗,這部份要特別說明,與一般的 Client/ Server 名詞定義有點差異,X Server 定義為 Display Server,而 應用程式端稱為 X Client。

● X Client:在 X Window 下的應用程式,要求特定的 X Server 作特定的 動作。主要的工作為:1、向 X Server 提出需求,2、接收來自 X Server 的事件訊息,3、接收來自 X Server 的錯誤訊息。

● X Protocol:X Client 和 X Server 的通訊協定,定義 Requests、Reply、

Error 和 Events。

● X Library:簡稱 X Lib,大部分 X window 上的應用程式以 X Library 來 建立 GUI 元件,例如:按鈕(bottom)、目錄(menus)等等。

2.1.4 遠端桌面程式比較 遠端桌面程式比較 遠端桌面程式比較 遠端桌面程式比較

根據先前介紹的遠端桌面系統,這節將對系統特性以及更新方式做個比較。

1. 畫面更新方式 畫面更新方式 畫面更新方式 畫面更新方式

Server 和 Client 之間的畫面更新方式可以分為以下幾種:

● RAW:所有的更新圖片,不經過壓縮編碼,每個 pixel 的資料依序傳送,

可以想像資料量很大,假設傳送一張 640 x 480 大小的 16 位元高彩圖片,

就需要 614.4K Bytes。VNC 有支援這樣的編碼方式機制。

●2D draw primitives:利用區塊填色的方法將圖形編碼,通常是一種非失 真編碼的方式,VNC 畫面編碼主要是以這樣的方法。

●Low level graphic:除了圖形編碼的方法之外,還利用一些簡單的指令,

例如:字型、多邊形、線條等等的指令呼叫 Client 繪圖,RDP 便是利用這 樣的更新方式進行畫面更新。

●High level graphic:除了 2D draw primitives 和 Low level graphic,還支 援視窗的建立和管理,X Window 所利用的 X Protocol 就是屬於這類。

2. Server/Client 訊息傳遞方式 訊息傳遞方式 訊息傳遞方式 訊息傳遞方式

Server 和 Client 的訊息傳遞方式主要可以分為兩種,Server Push 就是 由 Server 主動決定何時傳送更新畫面到 Client;Client Pull 就是由 Client 向 Server 要求傳送更新,使用 Server Push 的系統,其畫面更新較為平順 但是相對資料量較大,而 Client Pull 則是只有在使用者輸入訊息時,才會 通知 Server 作畫面更新的傳送,但是其資料量較少。

瞭解了畫面編碼方式及系統更新方式,根據這些特點我們將針對這幾個系統做分 析比較,說明如表 1.。[4]

表 2-1.遠端桌面系統比較

系統 畫面編碼方式 更新方式 壓縮方式 cache license VNC Compressed

Pixel Data

Client pull

2D draw primitives

Client frame

buffer GPL

VNC 的信令、溝通格式、編碼…等,完全是依照「RFB Protocol」所規定,

因此,不論是任何版本的 VNC 皆須遵照此 protocol。RFB(Remote Frame Buffer) 是一個定義遠端圖形用戶終端介面的簡單協定,因為它是用在 FrameBuffer 上,

所以它適用於所有視窗作業系統和視窗程式,包括:X11、Windows 和 Mac。使 用者端稱為 RFB Client,另一端則是 FrameBuffer 的源頭,可以是視窗系統和程 式,稱為 RFB Server,如圖 1。

圖 2-1.VNC 系統架構

RFB Protocol 設計時考量的重點中,就強調 Client 端只需要相當少的需求,

因此它可應用於廣泛的硬體上,目前市面上更出現相關的軟體,如 Smart VNC,

讓手機也可以連上個人電腦,其方便性可見一斑。

2.2.1 RFB Protocol 組成要素 組成要素 組成要素 組成要素

此小節要初步介紹構成 RFB 的幾大要素。

1. Display Protocol

Display Protocol 是 以 一 個 很 原 始 且 簡 單 的 概 念 為 基 礎 : 「 將 server Framebuffer 中,一個矩形所有的 pixel 資料,放在所屬 client 對應的位置上」。

由許多的矩形組成一張完整的 Framebuffer,直覺上可能很沒效率,但深入探討 後,當畫面只有一些小區塊變動而不是整張 Framebuffer,此時只需更新那區塊 的矩形,加上其允許不同的編碼格式,提供了網路頻寬、使用端畫面更新和伺服 端處理速度,相互間的取捨!

FrameBuffer 的變動,會促成 Server 送出一連串矩形的更新,但這個更新的 機制是由 Client 為需求導向,即 Client 送出要求更新的訊息,Server 才會將資料 送出。一般在本地端,更新 Framebuffer 是很快速的一個接著一個,Client 只需 要持續的接收資料、解封包、更新本地端的畫面,接著再送出更新的需求,對於 較次一級的 Client 或網路,當 Client 端更新速度跟不上 Server 端 Framebuffer 變化時,一些 Framebuffer 的暫態會被忽略掉。

2. Input Protocol

Protocol 的輸入端,是由標準的一組鍵盤,和多按鍵的點選裝置所組成!輸入 的事件,無論使用者何時按了按鍵或移動裝置,都只由 Client 端傳送訊息給 Server 端。輸入裝置也可以是不標準的 I/O,如手寫板,他們的辨識引擎會自動產生鍵 盤的對應事件,因此 Server 還是可以正確的判斷!

3.

Pixel 資料表示 資料表示 資料表示 資料表示

在 pixel 資料要被傳送時,RFB Client 和 Server 溝通中會包括格式和編碼,

這個溝通是為了讓 Client 的工作簡單化而設計。底線是 Server 要提供 Client 想 要的 pixel 資料格式,如果 Client 有能力處理許多不同的格式和編碼,它會選一 個 Server 較容易產生的。

(1) Pixel 格式:個別顏色如何用 Pixel 值來表示,最常見的格式是 24-bit 或 16-bit,這些 bit 會直接被轉譯成紅、綠、藍的顏色。而 8-bit 的”colour map”,

可以通過 mapping,把 pixel 值轉成 RGB 的顏色!

(2)編碼:一個矩形的 pixel 資料如何被傳送。每一個矩形的 pixel 資料,會先 用一個標頭記錄這個矩形在螢幕中 X、Y 的位置、長、寬,和編碼的種類,而 編碼資料會接在標頭之後被傳送出去。常用的編碼種類有 Raw、CopyRect、

RRE、Hextile 和 ZRLE。一般都是使用 ZRLE、Hextile、CopyRect,因為他 們提供最佳的壓縮效率!

4.

溝通訊息 溝通訊息 溝通訊息 溝通訊息

RFB Protocol 可以應用在任何可靠的傳輸中,一般是在 TCP/IP 上。

這個 Protocol 總共會有三個階段:

(1)Handshaking Phase:用來確認 protocol 的版本和安全性的種類 (2) Initialization Phase: Client 和 Server 會互相傳送初始化的訊息

(3)Normal protocol interaction: Client 可以傳任何他想送的訊息,Server 會回傳結果!所有這些訊息都會以 message-type 為開端,接著才是訊息的 資料!

Protocol 的訊息都是以以下幾種種類表示:U8、U16、U32、S8、S16、S32 各別是 unsigned 8、16、32bits 、signed 8、16、32bits,而所有多 bytes 都是 以 big endian 來 排 序 ! PIXEL 則 是 一 個 pixel 值 所 需 的 bytes 數 , 即 BytesPerPixel。

2.3 Win32 API

因為 VNC Server 和 Client 中,有許多功能需借用 Windows 的函數來完成,

如取得程式視窗的大小;畫面變動偵測,會用到訊息溝再來取得 Hook 偵測到的 變動範圍;透過 GDI 將桌面的 Framebuffer 存成 RGB 的記憶體陣列…等,還有 許許多多要借用 Win32 的 API,因此此節要介紹較重要的 API,其他部分則會在 後續的章節陸續介紹。

2.3.1 視窗程式建立流程 視窗程式建立流程 視窗程式建立流程 視窗程式建立流程

此小節要介紹和一個很重要的概念:Handle,和完整 Win32 程式建立流程。

●Handle 概念

視窗程式全都是模組化的程式--每個視窗元件,例如選單、捲軸、按鈕等,

都是一個獨立的個體,每個個體或元件都有自己的資料和函數,由於一個程式有 可能會有多個相同種類的元件(例如一個程式裡有很多按鈕),那麼在眾多相同的 元件中,要決定控制哪個元件,就需要設定 Handle,來指明控制哪個元件,例 如視窗程式的主視窗,就需要一個 Handler,來指明使用者現在正控制該程式的 視窗,而非其他,故 Handler 的概念非常重要。

●Win32 程式建立流程[5]

int PASCAL WinMain(……)

{ HWND hwnd; //宣告程式的 Handle

MSG msg; //宣告 MSG 結構來存放訊息 WNDCLASS wc;//宣告類別結構

InitWindow( …) ) //創建主窗口

while (GetMessage(&msg, NULL, 0, 0)) //訊息迴圈 { TranslateMessage(&msg); //解析 msg

DispatchMessage(&msg); //呼叫訊息處理函數 }

接著在 InitWindow(…)中,會先對類別結構 WNDCLASS 做設定,然後調用 RegisterClass()對該類別進行註冊。因為每個視窗程式都有一些基本的屬性,如

2.3.2 訊息迴圈 訊息迴圈 訊息迴圈 訊息迴圈

將這些訊息一個個的取出來,放進一個 MSG 結構中去。GetMessage()函數原型 如下:[6]

BOOL GetMessage(

LPMSG lpMsg, //指向一個 MSG 結構的指標,用來保存訊息 HWND hWnd, //指定哪個視窗的訊息將被獲取

UINT wMsgFilterMin, //指定獲取的主訊息值的最小值 UINT wMsgFilterMax //指定獲取的主訊息值的最大值 );

GetMessage()將獲取的訊息複製到一個 MSG 結構中。如果佇列中沒有任何 訊息,GetMessage()函數將一直空閒直到佇列中又有訊息時再返回。如果佇列中

該結構中的主訊息表明了訊息的類型,例如是鍵盤訊息還是滑鼠訊息等,副 參數是用來過濾 MSG 結構中主訊息值的,主訊息值在 wMsgFilterMin 和 wMsgFilterMax 之外的訊息將被過濾掉。如果這兩個參數為 0,則表示接收所有 訊息。當 GetMessage()函數在獲取到 WM_QUIT 訊息後,將返回 0 值,程式將 退出訊息迴圈。

●訊息處理函數

TranslateMessage()函數的作用是把虛擬鍵訊息轉換到字元訊息,以滿足鍵 盤輸入的需要。DispatchMessage()函數的工作是把當前的訊息,發送到該應用 程式對應的訊息處理函數去。

LRESULT CALLBACK WindowProc( //訊息處理函數 HWND hwnd, //接收訊息視窗的控制碼

Default:DefWindowProc(hWnd, uMsg, wParam, lParam); } }

Windows 的訊息處理函數有一個確定的樣式,即這種函數的參數個數和類型 以 及 其 返 回 值 的 類 型 都 有 明 確 的 規 定 。 訊 息 處 理 函 數 的 四 個 參 數 是 由 GetMessage()函數從訊息佇列中獲得 MSG 結構,然後分解後得到的。第二個參 數 uMsg 和 MSG 結構中的 message 值是一致的,代表了主訊息值。程式中用 switch 語句來將不同類型的訊息分配到不同的處理程式中去。

值 得 注 意 的 是 , 應 用 程 式 發 送 到 視 窗 的 訊 息 遠 遠 不 止 以 上 這 幾 條 , 像 WM_SIZE、WM_MINIMIZE、WM_CREATE、WM_MOVE 等這樣常常使用 的 訊 息 就 有 幾 十 條 。 為 了 減 輕 編 寫 程 式 的 負 擔 , Windows 的 API 提 供 了 DefWindowProc()函數來處理這些最常用的訊息,調用了這個函數後,這些訊息 將按照系統默認的方式得到處理。因此,在 switch_case 語句中,只須明確的處 理那些有必要進行特別回應的訊息,把其餘的訊息交給 DefWindowProc()函數來 處理,是一種明智的選擇,也是你必須做的一件事。

●結束訊息迴圈

當用戶按 Alt+F4 或單擊視窗右上角的退出按鈕,系統就向應用程式發送 一條 WM_DESTROY 的訊息。在處理此訊息時,調用了 PostQuitMessage()函 數,該函數會給視窗的訊息佇列中發送一條 WM_QUIT 的訊息。在訊息迴圈中,

GetMessage()函數一旦檢索到這條訊息,就會返回 FALSE,從而結束訊息迴圈,

隨後,程式也結束。

2.3.3 WM_PAINT

Windows 裡有各種功能的訊息,功能和格式各有不同,限於篇幅,這邊就不 一一贅述,但遠端遠桌面系統最重要的便是得知畫面變動,進而壓縮這些區域傳

Windows 裡有各種功能的訊息,功能和格式各有不同,限於篇幅,這邊就不 一一贅述,但遠端遠桌面系統最重要的便是得知畫面變動,進而壓縮這些區域傳