2014年11月10日 星期一

「技術的原理」VNC(RFB 協定)

本篇是俺以過去的一些經驗,加上網上找到的資料做個紀錄,若有錯誤請不吝指正。

WIKI 上的解釋(截錄一小部份)

VNC(Virtual Network Computing),為一種使用RFB協定的螢幕畫面分享及遠端操作軟體。VNC由Olivetti & Oracle研究室所開發,此研究室在1999年併入美國電話電報公司(AT&T)。AT&T於2002年中止了此研究室的運作,並把VNC以GPL釋出。

原來的AT&T版本已經不再使用,因為更多有重大改善的分支版本已經出現, 像是RealVNC, VNC tight 和UltraVNC, 他們具有全面的向後兼容。至少對於基本的遠程控制功能而言。 Real VNC 是當前最活躍和強大的主流應用。








上圖是VNC的運作概念,RFB Server,也就是所謂的被控端,傳送有變化的螢幕區塊到RFB Client端,然候RFB Client則傳送滑鼠,鍵盤指令過去。而RFB對Client硬體要求不高,它只是把傳送過來的區塊資料繪圖在螢幕上 ,而把變化的區塊計算、壓縮等等的工作都落在Server身上。

基本上區塊的內容並不是固定的大小,視不同的範圍以及壓縮方法不同可能有所改變。區塊內的內容會包含區塊內容(可能是經過壓縮運算或RAW)、區塊左上角的X、Y位置(相對於Server螢幕),區塊的長寬高。

關於畫面的更新機制,其實Server並不是一直傳送更動區塊給Client,而是由Client端所驅動The update protocol is demand-driven by the client.)這樣有一個好處,當遇到Client端硬體較弱或是網路很差時,可以在client己繪完圖後再要求更新,或是依網路情況調整更新速度,給予RFB協定一定程度的彈性。值得注意的是,Server可能會合併數個FrameUpdateRequest,然候只回傳一次畫面更新。

輸入的協定為標準的鍵盤以及滑鼠(支援滾輪,左、右鍵),當然你也可以用手寫,經過識別後再模擬成鍵盤事件傳送過去(需自行實作或現有的資源做開發,例如我在手寫皮上手寫個C,被識別後就當做我按下C這個鍵傳送出去)。

在區塊資料上其實支援了幾種方式(編碼),Client會提交所支援的數種方法供Server端選擇,Server端會選擇對Server端最有利的方式處理。(However  if the client is able to cope equally with several different formats or encodings, it may choose one which is easier for the server to produce.)
當然您也可以自己實作編碼方式,只要Server端以及Client都實作支援自訂編碼即可。

-----------------------------------------------------------------------------------------------------------

像素格式常見有 8 位元的 colour map ,以及 16位元以及24位元的true colour 。
編碼的方式,主要有以下幾種,詳細在最後一節有說明。

 1.Raw encoding

2.Copy Rectangle encoding

3. RRE encoding

4.Hextile encoding


資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html

5. ZRLE encoding

資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html

Pseudo Encodings

編碼資料中對於偽編碼(Pseudo Encodings),Client可以對Server要求“pesudoencoding”,宣告其本身支援這一類型的擴充協定;假若Server不支援”pseudo-encoding”則會略乎此編碼。該注意的是Client必需假設Server不支援這類的擴充,直到Client從Server取得真正完成擴充認證。

資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html


下列圖表是各種VNC軟體對編碼的支援程度。可以注意到其實有些編碼方式並不在上述列表中,例如像tight, Ultra  等等,皆是後來分支新增的編碼方式。

Feature Matrix

Software   ↓Raw   ↓CopyRect   ↓RRE   ↓CoRRE   ↓Hextile   ↓ZRLE   ↓ZYWRLE   ↓zlib   ↓tight   ↓zlibhex   ↓Ultra   ↓UltraZip   ↓
libvncclientyyyyyyyyyyyy
libvncserveryyyyyyyyyyyy
tigervncyyyy?yynnynnn
ultravncyyyyyyyyyyyy
tightvncyyyy?yynnynnn
realvnc
qemuyynnynnynnnn
gtk-vncyyynyynnynnn


資料來源 http://wiki.qemu.org/Google_Summer_of_Code_2010/VNC#RRE


RFB協定可以依任何可靠的定協傳送資料 (如TCP/IP),即使byte-streamor。正常來說RFB主要透過TCP/IP達成連線。完成一個RFB協定有三個步驟:第一步為「handshaking phase」,此階段主要是去同意協定的版本及使用的安全型態;第二步為「initialization phase」,即對Server與Client互相交換「ClientInit」及「ServerInit」的訊息。第三步為「normal protocol interaction」,Client將能夠傳送任何它想傳送的訊息,然後接受Server回傳的結果。

資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html




















Protocol Messages

首先我們先了解RFB中使用的資料型別, 
U8, U16,U32  表示不帶正負號 8 ,16 ,32 bit
 INT8, INT16, INT32  表示帶正負號 8 , 16 ,32 bit. 

除了pixel本身的值以外,所以協定中用到的byte 皆使用big endian order 



會有Byte order的問題主要在於當需要表現超過255的數字時,需要兩個以上的Byte。此時,究竟要以代表比較小的數字的byte先放,還是代表比較大的數字 先放呢?以小的數字的Byte先放的作法就稱為little-endian。反之,以大的數字的byte先放的就稱為big-endian。 例如下列4組2進制 表示10進制的66051, 最高位元組先存,則為big-endian ,

00000000 00000001 00000010 00000011


若存成下列這副模樣,則為little-endian

先 00000011 然後 00000010 然後 00000001 最後 00000000


資料來源 http://www.dev.idv.tw/mediawiki/index.php/%E5%90%84%E7%A8%AE%E7%B3%BB%E7%B5%B1%E7%9A%84Byte_order

http://jyhshin.pixnet.net/blog/post/26587992-big-endian-(%E5%A4%A7%E9%A0%AD%E6%B4%BE)%EF%BC%8Clittle-endian-(%E5%B0%8F%E9%A0%AD%E6%B4%BE)




RFB 從交握到開始傳送畫面的運作模式如下圖



































協定版本
「Handshaking Phase」開始前,Server會傳送ProtocolVerstion的訊息給Client,好讓Client能夠知道Server端支援RFB的最高版本,隨而Client回應Server可使用的版本號碼(不一定與Server的版本號碼相同),正常來說,Client不該要求高於Server端RFB的版本。

ProtocolVersion message 內容是 12 bytes  ASCII characters  格式為  "RFB xxx.yyy\n" ,XXX為主要版本號,而yyy為次要版本號。 目前有以下三種可能。




No. of Byte
Value
Remark
12
“RFB 003.003\n” (hex 52 46 42 20 30 30 33 2e 30 30 33 0a)
3.3
12
“RFB 003.007\n” (hex 52 46 42 20 30 30 33 2e 30 30 37 0a)
3.7
12
“RFB 003.008\n” (hex 52 46 42 20 30 30 33 2e 30 30 38 0a)
3.8



安全性
一定協定版本確認後,Client、Server在連線時,必需協議共同的安全性標準。假若Client支援的安全性協定有在Server列舉的安全性協定清單中,Client會回傳單一byte的訊息告知Server某安全性協定可被用於這次的連結。  在進行Handshaking Phase時,不論這一階段的連成是否成立,Server都會傳送一個字串通知Client,假若連線成立,RFB協定即進行下一階段──Initialization Phase.
假若安全性連線失敗,Server則傳送一則字串描述此異常,隨後終止連結。

Server 必須傳送所支援的安全性清單,格式如下表


No of bytes
Type                         [Value]
Description
1
number-of-security-types
U8
U8 array
number-of securitry-types
security-types


如果 number-of security-types 為零,或發生版本無法支援等等,則Server端必須回應一個理由給Client後中斷連線


No.  of bytes
Type            [Value]
Description
4
reson-length
U32
U8 array
reason-length
reason-string

下列是安全性認證的列表



Number
Name
0
Invalid
1
None
2
VNC Authenication
5
RA2
6
RA2ne
16
Tight
17
Ultra
18
TLS
19
VenCrypt
20
GTK-VNC SASL
21
MD5 has authentication
22
Colin Dean xvp

Client回應選擇認證類型

No. of bytes
Type     [Value]
Description
1
U8
security-type


VNC認證
連線時,隨送傳送16位元的VNC認證,而協定資料不做加密的動作。Server會隨機產生一個16 byte的要求Client回應特定的訊息。Client依據Server傳送過來的16 byte編碼為金鑰,並加密回傳此金鑰以回應Server。而此更協定依據項些安全性協定的回應持續進行下去。

Server 16 byte 金鑰
No. of bytes
Type     [Value]
Description
16
U8
challenge

Client回覆內容
No. of bytes
Type     [Value]
Description
16
U8
response

Server回覆

No. of bytes
Type     [Value]
Description
4
U32
status:
OK
failed

在3.8版開始,如果Client回覆的認證Server不接受,則亦回覆一個錯誤原因


No.  of bytes
Type            [Value]
Description
4
reson-length
U32
U8 array
reason-length
reason-string


訊息初始化
當Client、Server建立安全性連結後,接著會進行初始化層段(initialsation phase)
這個階段,在Client傳送一個「ClientInit」,Server隨即會傳送「ServerInit」訊息。


ClientInit:
Client回應的訊息只有一個「shared-flag」參數,若值非「0」(true),則表式Server試著去持續共享桌面而不對其他的Client端做終止連線的動作,反之,若值為「0」(false),則表示終止其他連線,僅對某Client端提供桌面分享的服務。



No. of bytes
Type     [Value]
Description
1
U8
shared-flag


ServerInit:
Server 接受ClientInit訊息後,會接著發送ServerInit訊息,此訊息會告知Client端Framebuffer的長、寬、像素格式以及此桌面相關名稱。


No. of bytes
Type     [Value]
Description
2
U16
framebuffer-width
2
U16
framebuffer-height
16
PIXEL_FORMATR
server-pixel-format
4
U32
name-length
name-lenght
U8 array
name-string

PIXEL FOMAT


No. of bytes
Type     [Value]
Description
Remark
1
U8
bit-per-pixel
只能是8,16,32
1
U8
depth
位元深度(<= big-per-pixel)
1
U8
big-endian-flag
是否為big endian
1
U8
true-color-flag
是否使用true - color
2
U16
red-max
紅色最大值
2
U16
blue-max
藍色最大值
2
U16
green-max
綠色最大值
1
U8
blue-shift
在一組位元中,藍色必須位移多少
1
U8
red-shift
在一組位元中,紅色必須位移多少
1
U8
blue-shif
在一組位元中,綠色必須位移多少
3

padding


資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html
                  http://www.realvnc.com/docs/rfbproto.pdf

Client to server messages ( 由Client傳給Server的封包格式)


Client傳給Server的Message有以下幾種,下面會分別介紹各種Message的封包結構,Server依此表格Number做為識別封包是何種類型,才有辦法正確解毒(每一封Message的封包格式長度都不同)


Number
Name
Remark
0
SexPixelFormat
設定PixelFormat
2
SetEncodings
設定編碼
3
FramebufferUpdatReauest
要求更新畫面資訊
4
KeyEvent
鍵盤事件
5
PointVent
滑鼠事件
6
ClientCuText
剪貼簿

 SetPixelFormat


No. of bytes
Type     [Value]
Description
1
3
16
U8            0

PIXEL_FORMAT
message-type
padding
pixel-fromat

PIXEL_FORMAT


No. of bytes
Type     [Value]
Description
Remark
1
U8
bit-per-pixel
只能是8,16,32
1
U8
depth
位元深度(<= big-per-pixel)
1
U8
big-endian-flag
是否為big endian
1
U8
true-color-flag
是否使用true - color
2
U16
red-max
紅色最大值
2
U16
blue-max
藍色最大值
2
U16
green-max
綠色最大值
1
U8
blue-shift
在一組位元中,藍色必須位移多少
1
U8
red-shift
在一組位元中,紅色必須位移多少
1
U8
blue-shif
在一組位元中,綠色必須位移多少
3

padding


SetEncodings


No. of bytes
Type     [Value]
Description
1
1
2
U8            2

U16
message-type
padding
number-of-encodings

number-of-encodings repetitions



No. of bytes
Type     [Value]
Description
4
S32
encoding-type

FramebufferUpdateRequest



No. of bytes
Type     [Value]
Description
1
1
2
2
2
2
U8        3
U8
U16
U16
U16
U16
message-type
incremental
x-position
y-position
width
heigtht

在此值得注意的是,incremental這個值,如果你並未擁有或是遺失某一區塊的畫面資料時

你在呼叫FramebufferUpdateRequest 必須把incremental設為0 ,這樣Server才會傳送整塊的畫面過來,或incremental設為非零的值,Server傳來的可能是CopyRect encoding ,要你參照某一塊的頻色,以減輕網路傳送的資訊量。



KeyEvent

當您的鍵盤有輸入東西時,您可以透過key Evnet把您所輸入的內容傳輸過去
No. of bytes
Type     [Value]
Description
1
1
2
4
U8             4
U8

U32
message-type
down-flag
padding
key

值得注意的是down-flag, 當某個鍵被按下時,down-flag為非0的值,當此鍵被釋放後,down-flag為
0值。以下是key所代表的值。 除了部份的功能鍵(F1~F12 ,CTRL ,ALT等等),都相同於ASCII CODE,下面列出功能鍵的碼。值得注意的是shift 鍵只有在被按下時才會傳送。
Key Name
Keysym value
BackSpace
0xff08
Tab
0xff09
Return or Enter
0xff0d
Esc
0xff1b
Insert
0xff63
Delete
0xffff
Home
0xff50
End
0xff57
Page Up
0xff55
Page Down
0xff56
Left
0xff51
Up
0xff52
Right
0xff53
Down
0xff54
F1
0xffbe
F2
0xffff
F3
0xffc0
F4
0xffc1
---
---
F12
0xffc9
Shift(left)
0xffe1
Shift(right)
0xff22
Control(left)
0xffe3
Control(right)
0xffe4
Meta(Left)
0xffe7
Meth(Right)
0xffe8
Alt(left)
0xffe9
Alt(right)
0xffea


PointerEvent
button-mask 是一個8bit位元組,支援了滑鼠8個按鈕,1表示按下 ,0表示此按鈕沒有被按下,

但預設button 1表示左鍵,button 2表示中鍵,button 3 表示右鍵,而滾輪的滾動則由button 4及button5表示,例如button4按下表示滾輪向上滾動,button5按下表示滾輸向下滾動。

No. of bytes
Type     [Value]
Description
1
1
2
2
U8        5
U8
U16
U16
message-type
button-mask
x-position
y-position

ClientCutText
這東西就類似一個剪貼簿,在文字內容最後面必須要補一個AscII 10 ( 13免)


No. of bytes
Type     [Value]
Description
1
3
4
length
U8         6

U32
U8 array
message-type
padding
length
text





Server to client messages (Server傳送給Client的封包格式)



相對於client,Server端傳給Client的訊號花樣就沒那麼多種了。



Number
Name
Remark
0
FramebufferUpdate
回傳畫面資料
1
SetColorMapEntries
設定頻色的對應(當client使用 colur map)
2
Bell
請Client端逼一聲
3
ServerCuText
Server端的剪貼簿



FramebufferUpdate



No. of bytes
Type     [Value]
Description
1
3
2
U8        0

U16
message-type
padding
number-of-rectangles



No. of bytes
Type     [Value]
Description
2
2
2
2
4
U16
U16
U16
U16
S32
x-position
y-position
width
height
encoding-type

















如上圖所示,我們可以理解其實Server一次可能會傳N個rectangles給Client。
encoding-type 其實也是一個一個不同 種類編碼的封包,容我後面再一一詳細解說。


SetColourMapEntries

當Client端 colur-map 等於1時,表示使用頻色的映射 , 它和樓上的封包一樣,也是一列火車的型式,告訴Client端該怎樣傳送對應的頻色過來。


No. of bytes
Type     [Value]
Description
1
1
2
2
U8          1

U16
U16
message-type
padding
first-colur
number-of-colours





No. of bytes
Type     [Value]
Description
2
2
2
U16
U16
U16
red
green
blue














Bell 

當收到此封包時, Client端會發出"逼"一聲。所以它不必帶任何其他的資料,只有一個單純的message-type。
No. of bytes
Type     [Value]
Description
1
U8
message-type

ServerCutText



No. of bytes
Type     [Value]
Description
1
3
4
length
U8         3

U32
U8 array
message-type
padding
length
text





最後是最重要的Encodings 封包格式,其實也就是不同種類的螢幕畫面區塊編碼型的封包。

首先是各種Encodings對應的代碼以及所代表的名稱,有一些Number其實是代表著參數的變化,例如tight options ,則表示使用tight 這個Encoding時,會用到的參數,則透過tight options來做參數傳遞,例如圖像的品質、 壓縮程度


Number
Name
0
RAW
1
CopyRect
2
RRE
5
Hextile
16
ZRLE
-239
Cursor pseudo-encoding
-223
Cursor pseudo-encoding
4
CoRRE
6
zlib
7
tight
8
zlibhex
15
TRLE
17
Hitachi ZYWRLE
18
Adam Walling XZ
19
Adam Walling XZYW
-1 to -222

-224 to -238

-240 to -256
tight options
-257 to -272
Anthony Liguori
-273 to -304
VMWare
-305
gii
-306
popa
-307
Peter Astrand DesktopName
-308
Pierre Ossman ExtendedDesktopSize
-309
Colin Dean xvp
-310
OLIVE Call Control
-311
CursorWithAlpha
-412 to -512
TurboVNC fine-grained quality level
-763 to -768
TurboVNC subsampling level
0x574d5600 to 0x574d56ff
VMWare

Raw encoding


No. of bytes
Type     [Value]
Description
width × height × bytesPerPixel
PIXEL array
pixels

最基本的編碼方式,也就是代表由左到右掃描出來的像素值。所有版本的RFB協定都能支援此編碼。

CopyRect encoding


No. of bytes
Type     [Value]
Description
2
2
U16
U16
src-x-position
src-y-position

這就是編碼中的烤貝忍者卡卡西了,直接告訴你去抄那一點的位置。不過前提是要抄的那一點必須先有資料才行。



RRE encoding

RRE指rise-and-run-length,其基礎在於模擬一段的二維編碼。RRE編碼所包函的rectangle會以能夠被簡易的繪圖engines有效率而快速繪製的形式到達Client端。  RRE編碼的缺點在於無法適用於複雜的桌面,但仍能使用於某些狀況。RRE編碼的基礎在於分割某像素資料的rectangle成多個副屬的rectangle,每一個副屬的rectangle都包括了各別區塊的像素內容,而將這些副屬的rectangle組合後,將會得到原始的rectangel,這些最適的副屬區塊相對的容易被計算出來。這項編碼包括背景像素值,

資料來源 http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html


No. of bytes
Type     [Value]
Description
4
bytesPerPixel
U32
Pixel
number-of-subrectangles
background-pixel-value

number-of-subrectangles


No. of bytes
Type     [Value]
Description
bytesPerPixel
2
2
2
2
Pixel
U16
U16
U16
U16
subrect-pixel-value
x-position
y-position
width
height

資料來源  http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html
                 http://www.realvnc.com/docs/rfbproto.pdf

 Hextile encoding

Hextile編碼為RRE的一種延伸,其將rectangle分成16 x 16的區塊,可令其大小為每邊區塊4 bit,而一個被化分出來的rectangle共16bit。每個rectangle由左上開始往右下計算,先左而右,由上至下,而編碼的內容都會依據先前的rectangel排列模式做排列。假若一個rectangle的寬度並非16的倍數,則最後一個rectangel在劃份後的寬度將會小於16。高度的原理同於寬度。  每個區塊不管以Raw編碼或是RRE編碼都會有背景像素值(background pixel),若背景像素的數值同於前一區塊,則不需特別設定至新的區塊中。另一個狀況:若傳送資料是以Raw編碼,背景像素值則不需要做任何設定。假若所有的副屬區塊(subretangle)都擁有相同的背景像素值,可當做整個區塊的前景顏色像素值,僅做一次性的設定;前景像素可同於背景像素的指定方式,其不需特別設定至區塊中,可從前一個區塊中取得。假若先前的區塊是Raw或是SubrectColored的設定,當下的區塊就不會特別前景像素設定至當下的區塊中,但會以AnySubrects從前一區塊取得前景像素(假定前一區塊已經從更前面的區塊取得前景像素值)。


No. of bytes
Type     [Value]
Description
1
U8
               1
                2
                4
                8
                16
subencoding-mask:
Raw
BackgroundSpecified
ForegroundSpecified
AnySubrects
SubrectsColoured

BackgroundSpecified

假如subencoding-mask中的第1個位元設為1 ,則會帶有下列的背景值。


No. of bytes
Type     [Value]
Description
bytesPerPixel
bytesPerPixel
background-pixel-value

ForegroundSpecified


假如subencoding-mask中的第2個位元設為1 ,則會帶有下列的前景值。


No. of bytes
Type     [Value]
Description
bytesPerPixel
bytesPerPixel
foreground-pixel-value

AnySubrects

 假如subencoding-mask中的第3個位元設為1 ,則會帶有下列的subrectangles數量值。
 假如subencoding-mask中的第3個位元設為0 ,則整塊區域都是背景色。


No. of bytes
Type     [Value]
Description
1
U8
number-of-subrectangles


SubrectsColoured

假如subencoding-mask中的第4個位元設為1 , 則每一個subrectangle的值,由下列資料型態表示。


No. of bytes
Type     [Value]
Description
bytesPerPixel
1
1
PIXEL
U8
U8
subrect-pixel-value
x-and-y-position
width-and-height

假如subencoding-mask中的第4個位元設為0 ,且第3個位元設為1,則區域皆為前景色。
假如subencoding-mask中的第4個位元設為0 ,且第3個位元設為0,則區域皆為前景色。


No. of bytes
Type     [Value]
Description
1
1
U8
U8
x-and-y-position
width-and-height


每一個subrectangle  由2個byte來做定義,x,y座標以及長寬,第1個byte的最高4個位元表示X座標,較低的4個位元表示Y座標,第2個byte最高4個位元表示寬度,較低4個位元表示高度.

 ZRLE encoding
ZRLE代表的是Zlib1 Run-Length Encoding,擁有Z-lib的壓縮、劃分區塊的能力。在傳送的序列資料中,每個區塊由4 byte長的標頭開始,隨後接著由z-lib壓縮的資料。每個單z-lib序列物件主都會在RFB協定的連結中產生作用,所以編碼、解碼需定訂嚴格的順序。  Z-Lib的資料在解壓後,會產生64 x 64的區塊,其值由左至右、由上至下排列(同於Hextile),若資料的長寬bit數不是64的倍數,則最後一個區塊的長寬將會小於64 bit。  ZRLE利用CPIXEL(compressed pixel)技術,這方法同於一般的像素格式,其中所有的bit由(r,g,b)構成,不管(r,g,b)強度為何,true-colour-flag的值不會是0,bitperpixel的值是32,depth值會在24以下。ZRLE中,一個CPIXEL只會有3 byte的長度,亦可能包函最低顯著或最高顯著的(r,g,b)值。bytePerCPixel為ZRLE中CPIXEL的bytes數。  每個區塊以subbencoding type byte開始,假若區塊編碼的起始byte有做過任何設定,則代表此區塊已運行過或是已被清除等等。區塊最底部的7個位元指定著色的範圍,0代表沒有做任何著色;1代表區塊使用單一色系,2~127表示區塊共使用了多少的顏色。
資料來源  http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html



No. of bytes
Type     [Value]
Description
4
length
U32
U8 array
length
zlibData

CPIXEL


Raw pixel data. width × height pixel values follow (where width and height
are the width and height of the tile):


No. of bytes
Type     [Value]
Description
width × height × bytesPerCPixel C
CPIXEL array
pixels



1 - A solid tile consisting of a single colour. The pixel value follows:


No. of bytes
Type     [Value]
Description
bytesPerCPixel C
CPIXEL
pixelV alue

2 to 16 - Packed palette types. Followed by the palette, consisting of paletteSize(=subencoding) pixel values. Then the packed pixels follow, each pixel represented as a bit field yielding an index into the palette (0 meaning the first paletteentry). For paletteSize 2, a 1-bit field is used, for paletteSize 3 or 4 a 2-bitfield is used and for paletteSize from 5 to 16 a 4-bit field is used. The bit fields are packed into bytes, the most significant bits representing the leftmost pixel (i.e. big endian). For tiles not a multiple of 8, 4 or 2 pixels wide (as appropriate), padding bits are used to align each row to an exact number of bytes.




No. of bytes
Type     [Value]
Description
paletteSize × bytesPerCPixel
m
CPIXEL array
U8 array
palette
packedPixels



 Cursor pseudo-encoding

簡單講就是Clinet要求Server回傳滑鼠游標圖案,讓Clinet自己畫在Client端畫面上。
Client若對Server發送這一則指令,即表示Client將有能力在本地端劃出server mouse的位置,這能夠在慢速的連線中明顯提升畫面呈現的效果。Server傳送FreamebufferUpdate時,會同時在Cursor pseudo-encoding設定pesudo-rectangle的內容回應Client的更新要求。pesudo-rectangle的內容包函x-position及y-position,其指出server端Cursor的位置,而width、height分別為Cursor的像素,並依據bitmask來設定資料的內容(所謂的bitmask,其內容主要是由左向右、由上至下對像素值做線性排列。

資料來源  http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html


No. of bytes
Type     [Value]
Description
width × height × bytesPerPixel
floor((width + 7)/8) ∗ height
PIXEL array
U8 array
cursor-pixels
bitmask



DesktopSize pseudo-encoding


Client端對Server請求DesktopSize pseudo-encoding以告知本地端可應付Framebuffer中width、height值變動的狀況。Server通常會將這一個pseudo-rectangle設定至最後一個Framebuffer資料的DesktopSize pseudo-encoding中,而此項目中pesudo-rectangle的x-position及y-position會被乎略,width及height值會告知新的Framebuffer大小。

資料來源  http://greatcreatcreate.blogspot.tw/2009/09/rfb-vnc.html


沒有留言:

張貼留言