李 暉,鐘生海,王清理
(中國(guó)航天科工集團(tuán)第二研究院 七〇六所,北京 100854)
遠(yuǎn)程桌面技術(shù)是利用有線或無(wú)線網(wǎng)絡(luò)由一個(gè)終端遠(yuǎn)程控制另一個(gè)或多個(gè)終端[1],并且遠(yuǎn)程被控端的桌面界面圖像可以顯示于本地的控制端。使用本地控制端的設(shè)備對(duì)遠(yuǎn)程被控端設(shè)備進(jìn)行操控時(shí),如同直接操控遠(yuǎn)程設(shè)備,屏幕上顯示的是被控端的桌面圖像,并且可以操控鼠標(biāo)打開(kāi)被控端的應(yīng)用程序,瀏覽被控端設(shè)備中的文件資料等。
在不同的平臺(tái)之上有著各自獨(dú)立的遠(yuǎn)程桌面系統(tǒng),并且采用了不同的技術(shù)手段來(lái)實(shí)現(xiàn),例如微軟Windows系統(tǒng)常用的RDP(remote desktop protocol)遠(yuǎn)程桌面協(xié)議,蘋果Mac系統(tǒng)采用的ARD(apple remote desktop)蘋果遠(yuǎn)程桌面,而在Linux系統(tǒng)之上,各類VNC程序例如Tight VNC、Real VNC、Ultra VNC等較為常用。各類VNC程序主要框架基本一致,都包括了服務(wù)器端VNC Server、客戶端VNC Client以及用來(lái)連接服務(wù)器端與客戶端的RFB協(xié)議,本文研究了主流VNC遠(yuǎn)程桌面軟件的工作流程及原理,分析VNC遠(yuǎn)程桌面軟件存在的主要問(wèn)題,并提出了對(duì)該程序進(jìn)行優(yōu)化改進(jìn)的建議。
遠(yuǎn)程桌面軟件的流程分為初始化握手階段以及正常交互階段兩部分。在正常交互階段中,遠(yuǎn)程桌面軟件主要實(shí)現(xiàn)兩個(gè)功能,一個(gè)是遠(yuǎn)端系統(tǒng)桌面圖像的顯示,另一個(gè)是本地端對(duì)遠(yuǎn)端系統(tǒng)的控制。其中遠(yuǎn)端系統(tǒng)桌面圖像的顯示又涉及到圖像消息的傳輸、屏幕變化的檢測(cè)與圖像消息的壓縮編碼這3個(gè)重要組成部分,對(duì)遠(yuǎn)端系統(tǒng)的控制涉及到對(duì)鍵盤及鼠標(biāo)事件的模擬輸入。
基于RFB協(xié)議的遠(yuǎn)程桌面軟件工作流程分為兩個(gè)階段:初始化握手階段和正常交互階段。初始化握手階段主要進(jìn)行客戶端連接服務(wù)器時(shí)的認(rèn)證以及雙方協(xié)商服務(wù)器向客戶端發(fā)送圖像畫(huà)面消息時(shí)所采用的像素格式以及編碼方式。在正常交互階段中,服務(wù)器將根據(jù)初始化握手階段所協(xié)商的像素格式以及編碼方式,將圖像發(fā)送給客戶端,實(shí)現(xiàn)遠(yuǎn)程畫(huà)面的顯示;同時(shí)客戶端將鼠標(biāo)、鍵盤事件發(fā)送給服務(wù)器,實(shí)現(xiàn)對(duì)服務(wù)器的遠(yuǎn)程控制。
初始化握手階段主要分為協(xié)商版本號(hào)、協(xié)商認(rèn)證方法、雙方交換初始化消息、協(xié)商像素格式和編碼方式這4個(gè)步驟。
首先,服務(wù)器與客戶端雙方進(jìn)行握手,服務(wù)器將其所能支持的最高RFB協(xié)議版本號(hào)發(fā)送給客戶端,客戶端回復(fù)其所要使用的版本號(hào),其所使用的版本必須小于或者等于服務(wù)器的版本號(hào),目前主流的協(xié)議版本主要有3.3、3.7和3.8。
接著雙方協(xié)商所要進(jìn)行安全認(rèn)證的方式,主要分為兩種:NONE與VNC認(rèn)證,采用NONE方式則不需要驗(yàn)證,采用VNC認(rèn)證方式時(shí),則使用挑戰(zhàn)/應(yīng)答機(jī)制身份認(rèn)證方法,服務(wù)器向客戶端發(fā)送一個(gè)16字節(jié)的隨機(jī)數(shù),客戶端使用DES加密算法對(duì)其進(jìn)行加密處理,秘鑰采用用戶的密碼,將加密后的結(jié)果發(fā)送給服務(wù)器,服務(wù)器使用自己保存的密碼以同樣的方法對(duì)隨機(jī)數(shù)進(jìn)行處理,若處理得到的結(jié)果與客戶端發(fā)送過(guò)來(lái)的結(jié)果一致,則說(shuō)明客戶端輸入了正確的密碼,此時(shí)服務(wù)器將認(rèn)證成功的結(jié)果發(fā)送給客戶端,否則服務(wù)器則返回給客戶端認(rèn)證失敗的結(jié)果。
雙方認(rèn)證成功后,客戶端向服務(wù)器發(fā)送一個(gè)字節(jié)的客戶端初始化消息,該消息包含是否允許服務(wù)器共享屏幕的標(biāo)志位,如果該標(biāo)志位為真,則允許其它客戶端同時(shí)連入該服務(wù)器,否則只允許當(dāng)前客戶端連接服務(wù)器。之后服務(wù)器向客戶端發(fā)送服務(wù)器初始化消息,其中含有服務(wù)器的各種配置信息,包括:幀緩存的寬度和高度、像素格式以及桌面相關(guān)的名稱。其中像素格式包含了每個(gè)像素需要的位數(shù)、像素值中有用的位數(shù)和是否為真彩色等相關(guān)參數(shù),該像素格式為服務(wù)器原本的像素格式,并且在之后的發(fā)送圖像畫(huà)面消息中會(huì)沿用此格式,除非客戶端發(fā)送了設(shè)置像素格式消息,請(qǐng)求了另外一種像素格式。
客戶端如果要使用自己的像素格式,則向服務(wù)器發(fā)送設(shè)置像素格式消息,之后發(fā)送設(shè)置編碼格式的消息,該消息包括了客戶端所支持的所有編碼類型,先后次序按所期望使用的優(yōu)先級(jí)進(jìn)行排列,首位具有最高優(yōu)先級(jí),而后服務(wù)器對(duì)所使用的編碼類型進(jìn)行選擇。在此之后,服務(wù)器與客戶端雙方便進(jìn)入了正常的協(xié)議交互階段。
在服務(wù)器與客戶端進(jìn)行的正常交互過(guò)程中,客戶端不斷發(fā)送鼠標(biāo)、鍵盤以及請(qǐng)求屏幕畫(huà)面更新的消息,服務(wù)器則不斷發(fā)送屏幕畫(huà)面更新的數(shù)據(jù),從而實(shí)現(xiàn)遠(yuǎn)程顯示畫(huà)面以及遠(yuǎn)程操控的功能。
在VNC中,屏幕更新推送策略主要有兩種分別是客戶端主動(dòng)拉取更新策略(Poll機(jī)制)和服務(wù)端主動(dòng)推送的更新策略(Push機(jī)制)[2]。其中Push方式為服務(wù)器端每隔10 ms檢測(cè)是否有圖像的更新,若有則主動(dòng)把更新的畫(huà)面推送到客戶端。而Poll方式則需要客戶端主動(dòng)發(fā)送幀緩存更新請(qǐng)求消息來(lái)對(duì)服務(wù)器畫(huà)面的更新進(jìn)行一個(gè)請(qǐng)求,服務(wù)器端收到該消息后,檢測(cè)屏幕畫(huà)面更新情況,若有更新,則向客戶端發(fā)送畫(huà)面的更新。VNC默認(rèn)情況下采用惰性更新的Poll方式[3],因此其具有一定的自調(diào)節(jié)可適應(yīng)性,根據(jù)客戶端的處理速度以及當(dāng)前的網(wǎng)絡(luò)帶寬情況進(jìn)行相應(yīng)傳輸速率的調(diào)整,保證了遠(yuǎn)程桌面不會(huì)因網(wǎng)絡(luò)的延遲等因素造成畫(huà)面更新錯(cuò)誤的發(fā)生。
當(dāng)程序進(jìn)入正常交互階段后,客戶端需要不斷發(fā)送幀緩存更新請(qǐng)求消息以獲取服務(wù)器的畫(huà)面更新。該消息包含消息的類型(默認(rèn)為3)、是否為增量更新、所請(qǐng)求需要更新畫(huà)面左上角的(x,y)坐標(biāo)以及畫(huà)面的寬高。在通常情況下客戶端所請(qǐng)求的為服務(wù)器端的全屏信息[3],因此該消息中所請(qǐng)求需要更新畫(huà)面左上角的(x,y)坐標(biāo)默認(rèn)為 (0,0),寬高默認(rèn)為服務(wù)器畫(huà)面的寬高。增量更新代表著是否需要服務(wù)器發(fā)送客戶端所請(qǐng)求畫(huà)面的全部?jī)?nèi)容還是只需要發(fā)送變化的部分,因?yàn)橥ǔG闆r下,客戶端都保留著服務(wù)器幀緩存的副本,服務(wù)器只需要每次發(fā)送變化部分的更新即可保持客戶端與服務(wù)器的同步。但是某些情況下客戶端會(huì)丟失某一區(qū)域的內(nèi)容,那么它便需要服務(wù)器將該區(qū)域的全部?jī)?nèi)容發(fā)送過(guò)來(lái),此時(shí)發(fā)送幀緩存更新請(qǐng)求消息時(shí),需要將其中的增量更新標(biāo)志位設(shè)為false。而在通常情況下,客戶端不會(huì)丟失任何內(nèi)容,因此每次發(fā)送幀緩存更新請(qǐng)求消息時(shí),都將其中的增量更新標(biāo)志位設(shè)為true,服務(wù)器收到該消息后,會(huì)將其變化的內(nèi)容發(fā)送給客戶端。
當(dāng)服務(wù)器收到客戶端發(fā)送過(guò)來(lái)的幀緩存更新請(qǐng)求消息時(shí),會(huì)記錄這一消息,同時(shí)調(diào)用PollingManager類的對(duì)象的函數(shù)進(jìn)行屏幕變化的檢測(cè),若檢測(cè)到屏幕自上一次發(fā)送更新之后,又產(chǎn)生了新的變化,則向客戶端發(fā)送幀緩存圖像更新消息,若畫(huà)面沒(méi)有任何變化則不發(fā)送。同時(shí)服務(wù)器有一個(gè)計(jì)時(shí)器,每隔30 ms也會(huì)對(duì)屏幕的變化進(jìn)行一次檢測(cè),若檢測(cè)到屏幕的變化,同時(shí)還有客戶端的更新請(qǐng)求未處理時(shí),則會(huì)向客戶端發(fā)送最新的屏幕變化消息。該流程如圖1所示。
圖1 圖像更新流程
幀緩存更新圖像更新消息包含一系列像素?cái)?shù)據(jù)矩形,客戶端接收這些消息并解碼,而后顯示在自己的幀緩存中。其格式如下:首先為屏幕圖像更新消息的頭部,其中包含了消息的類型(默認(rèn)為0)、一字節(jié)的填充與所要發(fā)送的矩形塊的個(gè)數(shù)。接下來(lái)是所要發(fā)送的各個(gè)矩形塊的像素信息,包含了矩形塊像素信息的頭部和數(shù)據(jù)部分。其中頭部包含了矩形塊的左上角坐標(biāo)、寬、高以及所使用的編碼方式。數(shù)據(jù)部分為所使用指定編碼方式進(jìn)行編碼的圖像數(shù)據(jù)。
當(dāng)客戶端收到服務(wù)器發(fā)送過(guò)來(lái)的幀緩存更新圖像更新消息之后,會(huì)將其解碼,得到需要進(jìn)行更新的矩形塊的原始像素信息,根據(jù)像素信息填充到相應(yīng)的坐標(biāo)位置,便完成了一次屏幕圖像的更新。同時(shí)客戶端完成一次畫(huà)面更新后,會(huì)再次向服務(wù)器發(fā)送幀緩存更新請(qǐng)求消息對(duì)服務(wù)器進(jìn)行畫(huà)面更新的請(qǐng)求,循環(huán)往復(fù),這樣便實(shí)現(xiàn)了客戶端與服務(wù)器的同步顯示。
在Windows操作系統(tǒng)中,屏幕的變化通常可以通過(guò)系統(tǒng)鉤子(Hook)來(lái)獲取[4],因?yàn)樵趙indows系統(tǒng)中的應(yīng)用程序是基于消息驅(qū)動(dòng)的,所有的應(yīng)用程序通過(guò)對(duì)各種消息做出響應(yīng)進(jìn)而實(shí)現(xiàn)各種功能,而桌面的改變同樣也會(huì)產(chǎn)生相應(yīng)的消息,因此便可以通過(guò)系統(tǒng)鉤子獲取到屏幕的變化。
而在Linux中,RFB協(xié)議則基于幀緩存的掃描來(lái)實(shí)現(xiàn)屏幕變化的檢測(cè),即通過(guò)新舊幀緩存的對(duì)比,找出屏幕變化的部分,具體實(shí)現(xiàn)方法如下:
首先對(duì)屏幕進(jìn)行分塊,將屏幕分為一個(gè)個(gè)寬高均為32pixel的小塊,用m_changeFlags[]數(shù)組記錄改變標(biāo)志位,即記錄哪一個(gè)小塊發(fā)生了變化,另外用一個(gè)數(shù)據(jù)結(jié)構(gòu)保存舊的屏幕圖像。接下來(lái)便開(kāi)始按照從上到下從左到右的順序,對(duì)每一個(gè)小塊分別進(jìn)行掃描。對(duì)小塊的新舊圖像進(jìn)行對(duì)比時(shí),并不是對(duì)小塊的每一個(gè)像素點(diǎn)都進(jìn)行比較,而是只選取了其中的某一個(gè)橫排(即32個(gè)像素點(diǎn))作為代表,只掃描這一橫排,對(duì)比判定是否一致,若一致,則未發(fā)生變化,若不一致,則說(shuō)明該小塊的圖像發(fā)生了改變,之后將相應(yīng)的標(biāo)志位置為true記錄這一改變,這樣便減少了比較的次數(shù),極大地提高了程序的效率。而具體取哪一行作為小塊的代表,RFB協(xié)議的作者經(jīng)過(guò)測(cè)試,得出了以下的順序:m_pollingOrder[32]={0,16,8,24,4,20,12,28,10,26,18,2,22,6,30,14,1,17,9,25,7,23,15,31,19,3,27,11,29,13,5,21}, 即當(dāng)?shù)谝淮螔呙钑r(shí),每一次只比較每個(gè)小塊第0行的數(shù)據(jù),第二次比較時(shí),則比較每個(gè)小塊第16行的數(shù)據(jù),以此類推,如圖2所示。通過(guò)對(duì)每個(gè)小塊的掃描,便得到了屏幕變化的塊,服務(wù)器將這些變化的塊進(jìn)行編碼發(fā)送,客戶端便得到了最新的畫(huà)面。
圖2 屏幕變化的檢測(cè)流程
當(dāng)獲取到屏幕變化的圖像數(shù)據(jù)后,需要采取一定的壓縮編碼方法進(jìn)行處理后傳輸;在客戶端展現(xiàn)圖像時(shí),需用相應(yīng)的算法對(duì)其進(jìn)行譯碼便得到了服務(wù)器的圖像。而圖像的壓縮編碼方法是RFB協(xié)議的核心[5],關(guān)系著遠(yuǎn)程桌面?zhèn)鬏斔嫉膸捯约爱?huà)面的質(zhì)量。圖像的壓縮方法大體上分為如下兩類:①有損壓縮,即經(jīng)過(guò)相應(yīng)方法壓縮處理之后,無(wú)論采用何種算法進(jìn)行譯碼處理,所獲得的圖像與原始的圖像相比總會(huì)產(chǎn)生一部分失真,因?yàn)槠湓试S一些數(shù)據(jù)的流失,因此此種壓縮方法通常有著比較高的壓縮比率;②無(wú)損壓縮,經(jīng)過(guò)壓縮處理后,采用一定的算法進(jìn)行譯碼處理,得到的圖像與原始的圖像數(shù)據(jù)完全一致,不產(chǎn)生任何失真,還原度高,但由于其保留著所有的圖像數(shù)據(jù),通常這類壓縮方法的壓縮比率會(huì)比較低[6]。目前RFB協(xié)議支持許多圖像壓縮處理方法,包含Raw編碼、CopyRect編碼、RRE編碼、CoRRE編碼、Hextile編碼、ZRLE編碼以及偽編碼等,下文將對(duì)其中幾種具有代表性的編碼進(jìn)行簡(jiǎn)單介紹。
2.3.1 Raw編碼
Raw編碼,即原始編碼,該編碼不進(jìn)行任何的數(shù)據(jù)壓縮,保留原始的圖像數(shù)據(jù)。此方法在同等條件下傳輸所占用的帶寬最大,傳輸效率最低,但是因其不進(jìn)行任何的編碼處理,所以對(duì)CPU處理的負(fù)荷比較小。所有RFB服務(wù)器都必須支持Raw編碼方式,通常情況下,如果客戶端不特別請(qǐng)求使用別的編碼方式,則服務(wù)器則默認(rèn)使用Raw編碼方式進(jìn)行處理。
Raw編碼的處理方法如下:對(duì)于要進(jìn)行編碼處理的矩形圖像塊,從其左上角開(kāi)始,從左到右,逐行對(duì)每一個(gè)像素點(diǎn)進(jìn)行掃描,并按照其像素?cái)?shù)據(jù)格式依次放入內(nèi)存的編碼區(qū)域。假設(shè)像素的格式為32位真彩色,則一個(gè)像素占4個(gè)字節(jié),若所要發(fā)送的矩形區(qū)域高為height、寬為width,則這個(gè)矩形區(qū)域采用Raw編碼所占總大小為4*height*width個(gè)字節(jié)。Raw編碼是最為簡(jiǎn)單的一種編碼方式,在內(nèi)存中編碼后的數(shù)據(jù)與矩形內(nèi)的像素點(diǎn)一一對(duì)應(yīng),此編碼方法為其它編碼方法的設(shè)計(jì)基礎(chǔ)。
2.3.2 CopyRect編碼
CopyRect編碼,對(duì)于在客戶端緩存中已有某些相同的圖像數(shù)據(jù)區(qū)域,但是其位置發(fā)生改變的情況下十分有效,該編碼僅包含待更新圖像數(shù)據(jù)區(qū)域的坐標(biāo),客戶端將已有的圖像數(shù)據(jù)直接復(fù)制到指定坐標(biāo)即完成了一次圖像的更新。也就是說(shuō),算法只需要在第一次將矩形的所有像素?cái)?shù)據(jù)發(fā)送,而后在服務(wù)器端該矩形的位置可能發(fā)生變化,但其矩形內(nèi)的像素內(nèi)容并沒(méi)有發(fā)生改變,因此接下來(lái)只需要發(fā)送該矩形當(dāng)前左上角的坐標(biāo)即可完成客戶端畫(huà)面的更新。而對(duì)于矩形的第一次發(fā)送時(shí)所采用的編碼方式并沒(méi)有加以限定,所以該編碼方法可以和其它編碼方式結(jié)合使用,以達(dá)到更好的效果。該算法可以應(yīng)用于許多種情形,其中最明顯的就是當(dāng)用戶在屏幕上移動(dòng)程序窗口的時(shí)候,采用該編碼方法會(huì)極大地減少帶寬的使用,提高傳輸效率。
2.3.3 RRE編碼
RRE編碼(rise-and-run-length encoding),正如它的名字所示,它的本質(zhì)是RLE編碼(run-length encoding),為其在二維空間上的實(shí)現(xiàn)。該編碼的主要思想是將要傳送的圖像區(qū)域劃分為一些子塊,其中每個(gè)子塊的像素點(diǎn)顏色都一致,將這些子塊作為整體進(jìn)行傳輸,可以極大程度上減少數(shù)據(jù)的重復(fù)表示。該編碼主要利用了圖像空間關(guān)聯(lián)的特性,也就是空間中相鄰像素的值通常一致或近似,因此該編碼方法在一些圖像較為簡(jiǎn)單的情況下十分有效,在復(fù)雜的桌面環(huán)境下效果差強(qiáng)人意。
該編碼的具體方法如下:首先在所要發(fā)送的像素矩形中找到一個(gè)出現(xiàn)頻率最高的像素值Vb,將該像素值作為該矩形的背景色進(jìn)行傳送。然后將矩形分為一個(gè)個(gè)顏色一致的子塊,子塊個(gè)數(shù)記為N,將子塊的個(gè)數(shù)發(fā)送給客戶端。接下來(lái)便要發(fā)送所有小子塊的像素信息,格式為
2.3.4 Hextile編碼
Hextile編碼[7]為RRE編碼的變種,該編碼會(huì)將所要進(jìn)行編碼處理的圖像細(xì)分為16*16的小塊,這樣可以壓縮控制參數(shù)所占的空間,可以僅僅用4 bits分別表示塊的長(zhǎng)度或?qū)挾?,也就是說(shuō)塊的左上角坐標(biāo)(x,y)可以用一個(gè)字節(jié)來(lái)表示,塊的寬度及高度(w,h)也可以只用一個(gè)字節(jié)來(lái)表示。排列順序按照從左到右、從上到下依次進(jìn)行編碼,若圖像的寬度非16的整數(shù)倍,則每行最右側(cè)的塊的寬度會(huì)進(jìn)行相應(yīng)地減少,同樣地如果高度非16的整數(shù)倍,每列最下側(cè)的塊的高度也會(huì)相應(yīng)減少。
對(duì)于每一個(gè)小塊的圖像數(shù)據(jù)的編碼方式,可以采用Raw編碼,也可以采用RRE編碼的變種,該變種同樣要選擇出現(xiàn)頻率最高的像素顏色作為背景色,之后要將小塊再分成一系列的小矩形,其中小矩形中的每個(gè)像素都含有相同的顏色,然后便是將背景色與這些小矩形的數(shù)據(jù)發(fā)送即可。而與RRE編碼不同的是,其中的背景色與前景色可以不用明確地寫出,當(dāng)不寫明時(shí),便會(huì)沿用上一個(gè)小矩形所使用的數(shù)據(jù)信息,節(jié)省了數(shù)據(jù)空間,提高傳輸效率。
2.3.5 幾種編碼的測(cè)試
通過(guò)在Linux系統(tǒng)下使用VNC軟件,對(duì)幾種主流編碼方式所占用的帶寬進(jìn)行測(cè)試后發(fā)現(xiàn):當(dāng)進(jìn)行一些簡(jiǎn)單操作并且圖像變化不大時(shí),使用各種算法效果均令人滿意。但是當(dāng)服務(wù)器的桌面分辨率較高,并且圖像快速變化時(shí),則會(huì)出現(xiàn)畫(huà)面殘影現(xiàn)象,并且流暢度不夠高。使用Raw原始編碼雖然可以提高流暢度,但會(huì)顯著提高帶寬的消耗,經(jīng)測(cè)試,使用Raw編碼在正常使用中平均占用帶寬10 Mb/s,若讓屏幕圖像快速變化,最高占用帶寬60 Mb/s。使用RRE等壓縮編碼雖然可以顯著降低帶寬,在實(shí)際使用中大約占用帶寬2 Mb/s,但是由于需要利用CPU對(duì)圖像編碼數(shù)據(jù)進(jìn)行額外的處理,因此圖像的快速變化又會(huì)導(dǎo)致電腦的流暢度降低。
客戶端不斷檢測(cè)鼠標(biāo)的移動(dòng)、按鍵的點(diǎn)擊與釋放等事件,當(dāng)此類事件發(fā)生時(shí),便會(huì)向服務(wù)器發(fā)送相應(yīng)鼠標(biāo)事件的消息,從而對(duì)服務(wù)器進(jìn)行控制。鼠標(biāo)消息的格式見(jiàn)表1。
表1 鼠標(biāo)消息格式
鼠標(biāo)消息的第一項(xiàng)為消息類型,這里默認(rèn)值為5。接著是按鍵掩碼,由1字節(jié)表示,也就是8 bit,鼠標(biāo)的每個(gè)按鈕分別對(duì)應(yīng)其中的每一位,例如0號(hào)位為true代表著沒(méi)有任何按鍵被按下,1、2和3號(hào)位分別對(duì)應(yīng)著鼠標(biāo)的左中右鍵被按下,4號(hào)位表示鼠標(biāo)滾輪往上滑,5號(hào)位表示鼠標(biāo)滾輪往下滑。(x,y)坐標(biāo)代表了當(dāng)前鼠標(biāo)所在的位置。
同樣地,客戶端也要對(duì)鍵盤的事件進(jìn)行監(jiān)測(cè),當(dāng)監(jiān)測(cè)到鍵盤按鍵的按下與釋放時(shí),都要發(fā)送鍵盤的消息給服務(wù)器,其中鍵盤消息格式見(jiàn)表2。
表2 鍵盤消息格式
其中消息類型的值這里默認(rèn)為4。當(dāng)鍵盤上某一按鍵被按下時(shí),按下標(biāo)志位為true,釋放時(shí)為false。然后發(fā)送2字節(jié)的填充,之后發(fā)送鍵號(hào)。在X Window中按鍵被賦值為keysym(鍵號(hào)),對(duì)于大多數(shù)按鍵來(lái)說(shuō),比如abcd等等,它們的鍵號(hào)與ASCII碼是相對(duì)應(yīng)的,而其它按鍵例如Delete、Insert等功能鍵則有另外的鍵號(hào)表示,具體參考Linux系統(tǒng)下的
Linux輸入子系統(tǒng)是Linux內(nèi)核用來(lái)管理各種輸入設(shè)備的,一般情況下,鼠標(biāo)和鍵盤設(shè)備分別對(duì)應(yīng)著/dev/input/event0和/dev/input/event1[8]。通過(guò)Input子系統(tǒng)可以實(shí)現(xiàn)對(duì)鼠標(biāo)以及鍵盤操作的模擬,例如假設(shè)當(dāng)前鍵盤設(shè)備為/dev/input/event1,可以向/dev/input/event1設(shè)備文件寫入一個(gè)字符“A”,這樣便相當(dāng)于通過(guò)鍵盤按下了A鍵,模擬了鍵盤的操作。
基于此種方式,客戶端向服務(wù)器發(fā)送鼠標(biāo)與鍵盤事件的消息后,服務(wù)器解析消息,并向相應(yīng)的鼠標(biāo)或鍵盤設(shè)備節(jié)點(diǎn)寫入數(shù)據(jù),模擬服務(wù)器的鼠標(biāo)或鍵盤操作,進(jìn)而實(shí)現(xiàn)了客戶端對(duì)服務(wù)器的遠(yuǎn)程操控。
基于RFB協(xié)議的遠(yuǎn)程桌面程序工作流程分為兩個(gè)階段:初始化握手階段和正常交互階段。初始化握手階段分為協(xié)商版本號(hào)、協(xié)商認(rèn)證方法、雙方交換初始化消息、協(xié)商像素格式和編碼方式這4個(gè)步驟。正常交互階段中,服務(wù)器通過(guò)將自己幀緩存中的內(nèi)容發(fā)送給客戶端實(shí)現(xiàn)了畫(huà)面的同步顯示,同時(shí)采用了只傳輸變化的部分以及運(yùn)用了多種編碼方式降低了畫(huà)面?zhèn)鬏斶^(guò)程中的帶寬占用率。并且采用了Poll方式,屏幕的畫(huà)面刷新完全由客戶機(jī)驅(qū)動(dòng),通過(guò)客戶端不斷發(fā)送幀緩存請(qǐng)求消息來(lái)請(qǐng)求畫(huà)面的更新,收到該請(qǐng)求后服務(wù)器處理該消息并向客戶端發(fā)送畫(huà)面的更新,這樣使得VNC程序具有了相當(dāng)?shù)淖赃m應(yīng)性,其畫(huà)面更新的快慢取決于當(dāng)前客戶端的處理能力以及當(dāng)前的網(wǎng)絡(luò)質(zhì)量,保證了傳輸?shù)姆€(wěn)定性。同時(shí)客戶端將其鼠標(biāo)與鍵盤的操作通過(guò)消息發(fā)送給服務(wù)器,服務(wù)器將其解析,并按照一定的格式向自己的鼠標(biāo)或鍵盤設(shè)備節(jié)點(diǎn)寫入相應(yīng)的數(shù)據(jù),模擬服務(wù)器端鼠標(biāo)或鍵盤的操作,實(shí)現(xiàn)了客戶端對(duì)服務(wù)器端的操控。
使用RFB協(xié)議的VNC程序,實(shí)現(xiàn)了遠(yuǎn)程桌面同步顯示與控制的功能,針對(duì)目前國(guó)產(chǎn)化發(fā)展應(yīng)用需求以及現(xiàn)狀,現(xiàn)有的VNC技術(shù)已經(jīng)不能滿足應(yīng)用需求,特別是在當(dāng)前國(guó)產(chǎn)處理器性能較低的情況下,為了進(jìn)一步提升VNC程序的性能,以滿足國(guó)產(chǎn)信息系統(tǒng)的新需求,筆者認(rèn)為其下一步的改進(jìn)優(yōu)化重點(diǎn)在于:
(1)圖像壓縮編碼的優(yōu)化:通過(guò)使用幾種主流的編碼方式進(jìn)行圖像傳輸測(cè)試后發(fā)現(xiàn):當(dāng)進(jìn)行一些簡(jiǎn)單操作并且圖像變化不大時(shí),使用各種算法效果均令人滿意。但是當(dāng)服務(wù)器的桌面分辨率較高,并且圖像快速變化時(shí),則會(huì)出現(xiàn)畫(huà)面殘影現(xiàn)象,并且流暢度不夠高。雖然隨著計(jì)算機(jī)技術(shù)的不斷進(jìn)步,網(wǎng)速以及CPU處理速度會(huì)不斷提高,二者均會(huì)使遠(yuǎn)程桌面軟件有著更好的體驗(yàn),但是依賴于硬件革新的同時(shí),也需要對(duì)軟件進(jìn)行不斷地優(yōu)化,研究如何保證畫(huà)面質(zhì)量的前提下進(jìn)一步減少帶寬的占用,同時(shí)在圖像快速變化時(shí)保證畫(huà)面的流暢度,另外現(xiàn)階段國(guó)產(chǎn)平臺(tái)CPU處理速度與國(guó)外主流CPU相比還有著些許差距,因此對(duì)于畫(huà)面的傳輸,需要對(duì)其圖像的壓縮編碼方式進(jìn)行進(jìn)一步的研究?jī)?yōu)化,以達(dá)到更好的使用效果。
(2)安全性的提高:在VNC的連接認(rèn)證中,采用了基于挑戰(zhàn)/應(yīng)答機(jī)制身份認(rèn)證的方法[9],比起傳統(tǒng)的靜態(tài)口令身份認(rèn)證,增加了隨機(jī)數(shù),通過(guò)隨機(jī)數(shù)的唯一性和多變性,增加了安全性,可以有效抵抗多種攻擊,但是其仍然存在著一些不足:例如服務(wù)器用于驗(yàn)證身份的密碼保存在服務(wù)器中,雖然其采用了Des進(jìn)行加密后存儲(chǔ),但是通過(guò)對(duì)幾個(gè)VNC程序的源碼進(jìn)行研究后發(fā)現(xiàn),其所使用的Des加密秘鑰都為 {23,82,107,6,35,78,88,7}, 因此黑客可以入侵服務(wù)器獲取密碼的密文,并通過(guò)此秘鑰解密獲得密碼的明文,從而可以連接到服務(wù)器對(duì)服務(wù)器進(jìn)行控制。另外在挑戰(zhàn)/應(yīng)答機(jī)制中的挑戰(zhàn)隨機(jī)數(shù)在網(wǎng)絡(luò)中是以明文的形式發(fā)送的,無(wú)任何保護(hù),易被黑客截取,而后可能采取離線密碼猜測(cè)攻擊獲得秘鑰的值[10]。同時(shí)RFB協(xié)議中服務(wù)器與客戶端正常交互的過(guò)程中,服務(wù)器畫(huà)面圖像的傳送以及鼠標(biāo)鍵盤消息的傳送都為明文傳送,同樣易被不法分子截獲,還原圖像從而使服務(wù)器上的隱私一覽無(wú)余。因此為了提升國(guó)產(chǎn)信息系統(tǒng)安全性,助力國(guó)家安全,基于國(guó)產(chǎn)平臺(tái)的遠(yuǎn)程桌面軟件需要使用更安全的認(rèn)證手段,比如智能卡、數(shù)字證書(shū)、USB KEY、生物認(rèn)證等多技術(shù)結(jié)合的多因素認(rèn)證方法,同時(shí)對(duì)RFB協(xié)議的正常交互階段均采用密文形式發(fā)送。
針對(duì)基于RFB協(xié)議的Linux遠(yuǎn)程桌面VNC程序,本文研究了其基本框架及流程,重點(diǎn)研究了圖像消息的傳輸、屏幕變化的檢測(cè)以及圖像的壓縮編碼方式,并對(duì)幾種編碼方式的效率進(jìn)行了測(cè)試。最后針對(duì)目前國(guó)產(chǎn)化發(fā)展應(yīng)用需求以及現(xiàn)狀,為了滿足全面國(guó)產(chǎn)信息系統(tǒng)的新需求,基于目前VNC所存在的問(wèn)題,提出了更進(jìn)一步的改進(jìn)優(yōu)化重點(diǎn),包括圖像壓縮編碼的優(yōu)化,以及安全性的提高,以實(shí)現(xiàn)基于國(guó)產(chǎn)平臺(tái)的安全遠(yuǎn)程桌面軟件。