(文章是基於剛剛做過的一個項目,對相關知識點進行總結回顧。主要內容均是對之前收集資料的總結概括,很多內容轉載自其它地方。因為時間比較長,沒有一一記錄轉載地址,特此感謝!)
一、簡介
RFB(遠程幀緩沖)是一個用於遠程訪問圖形用戶接口的簡單協議。適用於所有的桌面系統和應用,包括X11,Windows和Macintosh等。
RFB是基於tcp的一個應用層協議。
我們把用戶所在的一端(包括顯示器、鍵盤和鼠標)被稱為RFB客戶端。而幀緩沖發生變化的一端(桌面系統和應用)稱為RFB服務器。
RFB協議是一個瘦客戶協議。協議設計的重點是減小對客戶端的要求。這樣,客戶端可以運行在多種范圍的硬件上,實現的任務是使客戶端盡可能地簡單。
RFB協議也使得客戶端是“無狀態”的。如果一個客戶端和服務器斷開了連接,稍后再一次連接到這台服務器上,用戶的會話不會被關閉,狀態會一直保持着。不同的客戶端可以連接到同一個服務器上,在新的客戶端上用戶看到的是和原來的客戶端上相同的圖形用戶接口。這樣,用戶的桌面變的完全可移動了。只要有合適的網絡連接,用戶就可以訪問他個人的桌面應用,不論他走到哪里都可以連接到自己的會話上,而這些應用的狀態可以一直保持着。
二、顯示協議
RFB協議的顯示部分基於一個簡單的畫圖原理:“將一個矩形塊的象素點放在給定位置(x,y)上”。這樣做初看起來也許非常低效,因為要將用戶所有的圖形組件都畫出來。但是由於可以為象素數據進行多種不同的編碼,可以根據不同的參數比如網絡帶寬、客戶端計算速度和服務器處理的速度等選擇靈活的編碼方式。一系列的矩形塊組成了一個幀緩沖更新。一個更新描述了幀緩沖從一個狀態到另一個狀態的變化情況,所以,某些方面,這和音頻的幀很類似。
更新協議是客戶端“命令-驅動”型的。即服務器只有在收到客戶端的請求才向其發送更新。這使得顯示協議的質量可以調整。客戶端和網絡速度越慢,更新率就會越低。對於典型的應用,幀緩沖上相同區域的更新往往非常頻繁。如果客戶端或者網絡非常慢,由於非常低的網絡傳輸和客戶端更新,幀緩沖上瞬時的狀態都可以被忽略掉。
三、輸入協議
輸入協議是基於鍵盤和多鍵鼠標設備的標准工作站模型。當用戶敲了一下鍵盤或者鼠標,或者移動了一下鼠標,客戶端把這些輸入事件簡單地傳送給服務器。輸入事件可以由其它非標准I/O設備產生,如筆形手寫板引擎也可以生成鍵盤事件,之后服務端對事件進行相應處理。事件按照RFB協議規定的格式進行發送即可。
四、象素數據的表示
RFB客戶端和服務器最初的交互包括協商將要傳輸的象素數據的格式和編碼類型。協商被設計成使客戶端的工作盡可能的簡單。底線是服務器必須可以一直提供客戶端想要的象素數據的格式。但是如果客戶端可以處理多種編碼類型,它會選擇對服務器來說最容易生成的編碼。
象素格式是指象素值顏色表示法 最常用的象素格式是24位或16位真彩色。,它通過位來直接實現像素值到紅、綠、藍亮度的轉換。8 位“顏色映射”可以任意映射像素值到RGB亮度的轉換。
編碼是指怎樣通過網絡把矩形象素點的數據發送出去。每一個矩形象素點的數據被加了一個前綴包括它在屏幕上的位置,矩形象素點的寬度和高度,以及一個“編碼類型”來描述該象素的編碼方式。然后是經過編碼的數據本身。
目前的編碼方式主要有Raw、CopyRect、RRE、Hextile 和ZRLE.在實際應用中我們一般使用ZRLE、Hextile 和CopyRect,因為它們提供了典型桌面的最好壓縮。其他可能的編碼方式還包括,用於靜態圖片的JPEG和用於動態圖像有效傳輸的MPEG。協議可以通過增加新的編碼方式來進行擴展。(編碼的具體描述見其它文章)
五、協議擴展(添加新的編碼方式)
協議可以通過以下方式進行擴展:
新的編碼方式:
一種新的協議可以通過與現存的客戶端和服務端進行相關兼容的添加。因為現存的服務器將會忽略它們所不支持的新編碼方式。所以客戶端通過新的編碼方式進行請求也就不會有結果返回。
偽編碼方式:
除了真正的編碼方式,客戶端也可以請求“偽編碼”通告服務器,它支持某一協議的擴展。服務器如果不支持這種擴展,那么它將忽略。值得注意的是:客戶端必須先假設服務器端不支持這種擴展,直到它獲得服務器端支持的確認。
新的安全方式:
添加一個新型的安全方式會帶來無限的靈活性,它通過修改協議的一些行為,但是並沒有犧牲現存客戶端和服務器端的兼容性。客戶端和服務器端可以通過協議好的安全方式進行交流,當然並不一定與RFB協議類似。
無論如何你都不應使用不同的版本號。
RFB協議的版本是由RealVNC公司來制定的。如果你使用一個不同的協議版本可能與RFB/VNC不兼容,要保證協議的兼容性,請聯系RealVNC公司。這樣會減少在編碼方式和安全類型上的沖突。
六、 協議消息
RFB協議可以進行可靠的傳輸,如字節流或基於消息的。和大多數協議一樣,它也是通過TCP /IP協議簇連接。
協議由三步完成連接。
首先是握手報文,目的是對協議版本和加密方式進行協商。
第二步是初始化報文,主要用於客戶和服務器的初始化消息。
最后就是正常協議的交互,客戶端可以按需發送消息,然后可以獲得服務器的回復。
所有的消息以消息類型開始,接下來是特定的消息數據。
協議消息描述的基本類型有:U8、U16、U32、S8、S16、S32。(U表示無符號整數,S表示有符號整數。)
所有字節整數(除了像素值本身)遵從big endian順序。
不同的CPU有不同的字節序類型,這些字節序是指整數在內存中保存的順序。 最常見的有兩種: 1. Little-endian:將低序字節存儲在起始地址(低位編址) 2. Big-endian:將高序字節存儲在起始地址(高位編址) 例子1:在內存中雙字0x01020304(DWORD)的 存儲方式。 內存地址4000 4001 4002 4003 LE04030201 BE01020304 注:每個地址存1個字節,每個字有4個字節。2位16進制數是1個字節(0xFF=11111111)。 例子2:如果我們將0x1234abcd寫入到以0x0000開始的內存中,則結果為
|
big endian或者little endian跟cpu有關,從而影響整數在內存中的排列順序。big endian是高字節在前,little endian是低字節在前,網絡字節序一般是big-endian。
PIXEL代表一個像素值bytesPerPixel字節,8XbytesPerPixel = bits-per-pixel。