(注)この翻訳はひとつ前の RFB プロトコル バージョン 3.7 を元にしています。バージョン 3.8 の翻訳は下記リンク先にあります。


ソーシャルブックマーク: このページをはてなブックマークに追加 このページをDeliciousに登録 このページをlivedoorクリップに登録
サイト内関連リンク: RFB プロトコル 3.8


RFB プロトコル


Tristan Richardson
ReadVNC Ltd
(formerly of Olivetti Research Ltd / AT&T Labs Cambridge)*

Version 3.7
12 August 2003

目次


1 導入
2 表示プロトコル
3 入力プロトコル
4 ピクセルデータの表現
5 プロトコルの拡張
6 プロトコルメッセージ
6.1 ハンドシェイクメッセージ
6.1.1 ProtocolVersion
6.1.2 Security
6.1.3 ClientInitialisation
6.1.4 ServerInitialisation
6.2 クライアントからサーバーへのメッセージ
6.2.1 SetPixelFormat
6.2.2 FixColourMapEntries
6.2.3 SetEncodings
6.2.4 FramebufferUpdateRequest
6.2.5 KeyEvent
6.2.6 PointerEvent
6.2.7 ClientCutText
6.3 サーバーからクライアントへのメッセージ
6.3.1 FramebufferUpdate
6.3.2 SetColourMapEntries
6.3.3 Bell
6.3.4 ServerCutText
6.4 エンコード
6.4.1 Row
6.4.2 CopyRect
6.4.3 RRE
6.4.4 CoRRE
6.4.5 Hextile
6.4.6 ZRLE
6.5 擬似エンコード
6.5.1 カーソル
6.5.2 デスクトップサイズ

*James Weatherall, Andy Harter and Ken Wood also helped in the design of the RFB protocol

1 導入

RFB("remote framebuffer")はグラフィカルユーザインターフェイスにリモートアクセスを行うための単純なプロトコルです.このプロトコルはフレームバッファレベルで動作するため,X11やWindows 3.1/95/NT,Macintoshなどを含む,あらゆるウィンドウシステムに適合します.

ユーザが居る側(つまり,ディスプレイとキーボードやマウスがある側)の終端を,RFBクライアントと呼びます.フレームバッファへの変更が発生する側(つまり,ウィンドウシステムやアプリケーションが動作している側)を,RFBサーバーと呼びます.

RFBは真に"シン・クライアント"なプロトコルです.RFBプロトコルの設計は,クライアントにほとんど制約を課さないことに重きを置いています.そのため,クライアントは多彩なハードウェア上で動作しますし,クライアントを実装する作業は非常にシンプルです.

さらにこのプロトコルは、クライアントをステートレスにします.あるサーバーから切断したクライアントが後で同じサーバーに再接続した場合,ユーザインターフェイスは前の状態が保持されています.同じRFBサーバーに対して別のクライアントから接続することも出来ます.利用者は新しいクライアントから,最初のクライアントでのユーザインターフェイスと全く同じ状態を見ることになります.これは事実上アプリケーションを完全にモバイル化することが出来るということです.適切なネットワーク接続があるところならどこからでも,利用者は自分のアプリケーションにアクセスすることができます.そして,異なる場所からのアクセスに対して,アプリケーションの状態は保持されています.これにより,利用者がどこにいても,彼らが良く知っている同じコンピュータ環境を提供することができます.

2 表示プロトコル

このプロトコルの表示側は 「与えられた x, y 座標にピクセルデータとしての長方形を描画する」という単一の描画規則に基づいています.一見すると,これは多くのユーザーインターフェイス要素を描画するには非効率に思えるかもしれません.しかし,ピクセルデータに対して多様なエンコード方法を許可することにより,例えばネットワークの帯域やクライアントの描画能力,サーバーの処理能力といった,様々な要因のトレードオフを決定する上で,大きな柔軟性を与えています.

これら長方形のシーケンスは,framebuffer update(または単にupdate) を生成します.一回の更新は,ひとつの有効なフレームバッファから別のフレームバッファへの変更として表現されており,その点ではビデオの構造に似ています.通常、一回の更新中に現れる長方形が重なり合うことはありませんが、必ずしもそうである必要はありません.

更新プロトコルはクライアントからの要求によってのみ動作します.つまり,クライアントからの明示的な要求に対する応答によってのみ,サーバーからクライアントに更新が送られるということになります.この性質はこのプロトコルに適応能力を与えており,クライアントやネットワークが遅ければ遅いほど,更新の発生率は低くなります.典型的なアプリケーションでは,フレームバッファ上の同一エリア内への変更は次々と連続して発生する傾向があります.遅いクライアントや遅いネットワークの場合,フレームバッファ更新中のこの過渡的な状態を無視することができます.その結果,より少ないネットワークトラフィック,より少ないクライアント側の描画になります.

3 入力プロトコル Input Protocol

このプロトコルの入力側は,キーボードと複数ボタン付きポインティングデバイスという,標準的なワークステーションのモデルに基づいています.利用者がキーやボタンを押したりポインティングデバイスを動かしたりした場合には常に,入力イベントがクライアントからサーバーに伝えられます.これらの入力イベントは,他の非標準の入出力装置によって合成させることも可能です.例えば,ペンを使った手書き認識エンジンは,キーボードイベントを生成するかもしれません.

4 ピクセルデータの表現

RFBのクライアント・サーバー間の最初の対話は,送信されるピクセルデータのフォーマット およびエンコード形式 のネゴシエーションを含みます.このネゴシエーションは,クライアントの仕事が出来るだけ簡単になるように設計されています.最低限は,クライアントが要求する形式でサーバーがピクセルデータを常に提供できなければならない,ということです.しかしながら,クライアントがいくつかの異なるフォーマットやエンコードに対応している場合,サーバーが最も簡単に提供できるものを選択しても構いません.

ピクセルのフォーマット は,ピクセル値による個々の色の表現を表します.最も一般的なピクセルフォーマットは,24ビットまたは16ビットの"トゥルーカラー"(ピクセル値のビットが赤・緑・青の輝度をそのまま表す)と,8ビットの"カラーマップ"(任意のマッピングを使用してピクセル値からRGB値へ変換する)です.

エンコード形式は,ピクセルデータの長方形がどのように送信されるかを表します.全ての長方形のデータは,その先頭にヘッダとして,その長方形のスクリーン上での X, Y 座標,幅と高さ,そしてピクセルデータのエンコード形式を示すエンコードタイプ を持っています.データ自体は指定のエンコード形式でその後に続きます.

5 プロトコルの拡張

新しいエンコード形式を追加することでプロトコルを拡張することが出来ます.現時点で定義されているエンコード形式は,Raw, CopyRect, RRE, CoRRE, Hextile, そしてZRLE です.実際のところ,私達は通常 ZRLEHextileCopyRect だけを使用しています.これらは典型的なデスクトップにとって最も圧縮が効く形式だからです.

純正のエンコード形式に加えて,クライアントがある特定のプロトコル拡張をサポートしていることをサーバーに知らせるために,"擬似エンコード形式(pseudo-encoding)"を要求することが出来ます.その拡張をサポートしないサーバーはその要求を単純に無視するでしょう.その拡張独自の同意をサーバーから得られない限り,クライアントは,サーバーがその拡張をサポートしていないものと仮定しなければならない点に注意してください.

異なるタイプのエンコード形式や擬似エンコード形式が衝突しないことは重要です.このような問題を避けるため,RFB プロトコルのバージョンとエンコード形式は RealVNC 社によってメンテナンスされています.

各エンコード形式の説明は 6.4 を,擬似エンコード形式の意味については 6.5 を参照してください.

6 プロトコルメッセージ

RFBプロトコルは,任意の信頼できるトランスポート上(バイトストリームでもメッセージベースでも)で動作します.このプロトコルには二つのステージがあります.最初のハンドシェイクフェーズと,それに続く通常のプロトコルによる対話です.

ハンドシェイクはProtocolVersionSecurityClientInitialisationServerInitialisation の各メッセージから成ります.クライアントとサーバーの両方がProtocolVersion メッセージを送信することに注意してください.

ServerInitialisation メッセージの後,プロトコルは通常の対話を開始します.この段階になると,クライアントは自分の望むメッセージを送信することが可能で,その結果としてサーバーからのメッセージを受信します.これらのメッセージは1バイトのメッセージタイプ とそれに続くメッセージ固有のデータが続く形になります.

以下のプロトコルメッセージの説明では,基本的な型として U8,U16,U32,S8,S16,S32 を使用しています.これらはそれぞれ,8ビット,16ビット,32ビットの符号なし整数と,8ビット,16ビット,32ビットの符号付き整数を表します.複数バイト整数(ピクセル値は除く)はビッグエンディアン(最上位バイトを先頭に置く形式)です.

PIXEL型はピクセル当たりのバイト数 バイトのピクセル値を表します.ここで 8 × ピクセル当たりのバイト数は,クライアントとサーバーがServerInisialisationメッセージ(6.1.4)またはSetPixelFormatメッセージ(6.2.1)のどちらかで合意した「ピクセル当たりのビット数」になります.

6.1 ハンドシェイクメッセージ

6.1.1 ProtocolVersion

ハンドシェイクは,サーバーがクライアントにProtocolVersionメッセージを送信することで開始されます.これによりクライアントは,サーバーがサポートするRFBプロトコルの最も高いバージョン番号を知ります.その後クライアントは,実際に使用すべきプロトコルのバージョン番号(サーバーが示したバージョン番号と異なっていても構いません)を含む,同じようなメッセージを返します.クライアントはサーバーにより提示されたバージョンよりも高いバージョンを要求してはなりません.このメカニズムにより、サーバーとクライアントはある程度の下位互換性を持てるということを意味しています.

現時点で公開されているプロトコルバージョン番号は,3.3 と 3.7 だけです (以前、いくつかのクライアントによりバージョン 3.5 が誤って報告されましたが,全てのサーバーによってこれは 3.3 であると解釈されるべきです).通常,新しいエンコード形式や擬似エンコード形式を追加することはバージョン番号の変更を必要としません.サーバーは,理解できないエンコード形式を単に無視すれば良いからです.

ProtocolVersionメッセージは12バイトで構成され,ASCII文字で"RFB xxx.yyy\n"(xxx と yyy は,それぞれゼロ詰めされたメジャーバージョン番号とマイナーバージョン番号) という形式です.

バイト数
12 "RFB 003.003\n" (16進 52 46 42 20 30 30 33 2e 30 30 33 0a)

または

バイト数
12 "RFB 003.007\n" (16進 52 46 42 20 30 30 33 2e 30 30 37 0a)

の何れかです.

6.1.2 Security

プロトコルバージョンが決定した後,サーバーとクライアントはその接続で使用されるセキュリティタイプについて合意しなければなりません.

Version 3.7 サーバーはサーポートいているセキュリティタイプの一覧を返します.

バイト数 [値] 説明
1 U8 セキュリティタイプの数
セキュリティタイプの数 U8 array セキュリティタイプ

クライアントは,サーバーが示した一覧の中に自分がサポートするセキュリティタイプがひとつでも存在すれば,現在の接続で使用するセキュリティタイプを示す1バイトを送り返します.

バイト数 [値] 説明
1 U8 セキュリティタイプ

セキュリティタイプの数 がゼロの場合,何らかの理由(例えば,要求されたプロトコルバージョンをサーバーがサポートしていない等)で接続は失敗しています.その場合,理由を説明する文字列(長さとASCII文字から成る)が続きます.

バイト数 [値] 説明
4 U32 理由の長さ
理由の長さ U8 array 理由

理由 の文字列を送信した後,サーバーはその接続を終了します.

Version 3.3 サーバーがセキュリティタイプを決定し,1ワードを送信します.

バイト数 [値] 説明
4 U32 セキュリティタイプ

セキュリティタイプ には 0,1,2 の何れかが許されています.0 は接続が失敗したことを意味し,先に述べたような理由を説明する文字列が続きます.

セキュリティタイプ が決定すると,それに対応するデータ仕様は以下のようになります.

none (1) - 認証は不要で,プロトコルのデータは暗号化されずに送信されます.プロトコルはClientInitialisation メッセージへと続きます.

VNC authentication (2) - VNC認証が使用され,プロトコルのデータは暗号化されずに送信されます.サーバーは16バイトのランダムなチャレンジ数値を送信します.

バイト数 [値] 説明
16 U8 チャレンジ数値

クライアントはチャレンジ数値を使用してパスワードをDESで暗号化し,結果の16バイトを送信します.

バイト数 [値] 説明
16 U8 応答

サーバーは認証が成功したかどうかを1ワードで返します.成功した場合,プロトコルはClientInitialisation へと続きます.失敗した場合,サーバーは接続を終了します.

バイト数 [値] 説明
4 U8 応答:
0 成功
1 失敗
2 多すぎる(未使用)

6.1.3 ClientInitialisation

クライアントとサーバーが互いに合意したセキュリティタイプで通信する準備が出来ると,クライアントは初期化メッセージを送信します.

バイト数 [値] 説明
1 U8 共有フラグ

共有フラグ が非ゼロ(true)の場合,サーバーは他のクライアントとデスクトップを共有しようとします.ゼロの場合,サーバーは他のクライアントを切断することで,現在のクライアントに排他的なアクセスを与えます.

6.1.4 ServerInitialisation

ClientInitialisation メッセージを受け取った後,サーバーはServerInitialisation メッセージを送信します.このメッセージは,クライアントに,サーバーのフレームバッファの幅と高さ,ピクセルフォーマット,デスクトップに関連付けられた名前を伝えます.

バイト数 [値] 説明
2 U16 フレームバッファの幅
2 U16 フレームバッファの高さ
16 PIXCEL_FORMAT サーバーのピクセルフォーマット
4 U32 名前の長さ
名前の長さ U8 array 名前

PIXEL_FORMATは以下のような内容です.

バイト数 [値] 説明
1 U8 ピクセル当たりのビット数
1 U8 輝度
1 U8 ビッグエンディアンフラグ
1 U8 トゥルーカラーフラグ
2 U16 赤の最大輝度
2 U16 緑の最大輝度
2 U16 青の最大輝度
1 U8 赤のシフト値
1 U8 緑のシフト値
1 U8 青のシフト値
3 パディング

サーバーのピクセルフォーマット は,そのサーバーの自然なピクセルフォーマットです.クライアントが SetPixelFormat メッセージ(6.2.1)を使用して異なるフォーマットを要求しない限り,このピクセルフォーマットが使用されます.

ピクセル当たりのビット数 は,各ピクセル毎に使用されるビット数です.この値は,ピクセル値のうち有効なビット数を表す輝度 以上でなければなりません.現時点でピクセル当たりのビット数 は 8,16,32 の何れかでなければなりません.8 ビット未満はまだサポートされていません.ビッグエンディアンフラグ が非ゼロ(true)の場合,複数バイトのピクセルはビッグエンディアンであると解釈されます.当然ながら,ピクセル当たりのビット数 が8ビットの場合には意味がありません.

トゥルーカラーフラグ が非ゼロ(true)の場合,続く6項目により,ピクセル値から赤・青・緑の各輝度を抽出する方法が特定されます.赤の最大輝度 は赤色の最大値(= 2n - 1.ここで n は赤に使われるビット数)です.この値は常にビッグエンディアンであることに注意してください.赤のシフト値 は,ピクセル値の中から赤の値を得るために必要な,下位ビット方向へのシフト回数です.緑の最大輝度緑のシフト値青の最大輝度青のシフト値 は,それぞれ緑と青に対する同じ意味を持ちます.例えば,あるピクセル値から赤の値(0 〜 赤の最大輝度 )を得るためには次のように操作します.

ビッグエンディアンフラグ に従ってピクセル値を入れ替えます.(例えばビッグエンディアンフラグ がゼロ(false)で,ホストのバイトオーダーがビッグエンディアンなら入れ替えます)

赤のシフト値 だけ,右方向にシフトします.

・ホストのバイトオーダーに合わせた赤の最大輝度 と論理積をとります.

トゥルーカラーフラグ がゼロ(false)の場合,サーバーは赤・青・緑の輝度から成るピクセル値ではなく,カラーマップへのインデックスを使用します.カラーマップのエントリーは,サーバーがSetColourMapEntries メッセージ(6.3.2)を使用して設定します.

6.2 クライアントからサーバーへのメッセージ

6.2.1 SetPixelFormat

FrameBufferUpdate メッセージ内で使用されるピクセル値のフォーマットを設定します.クライアントがSetPixelFormatメッセージを送らなかった場合,サーバーはServerInitialisationメッセージ(6.1.4)で指定した,サーバー自身の自然なフォーマットを使用します.

トゥルーカラーフラグ がゼロ(false)の場合,"カラーマップ"が使用されることを示します.サーバーは,SetColourMapEntries メッセージ(6.3.2)を使用して任意のカラーマップを設定することが出来ます.これ以前にサーバーによってエントリーが設定されていたとしても,クライアントがこのメッセージを送った直後にカラーマップは空になります.

バイト数 [値] 説明
1 U8 0 メッセージタイプ
3 パディング
16 PIXEL_FORMAT ピクセルフォーマット

6.1.4で述べたのと同様,PIXEL_FORMATは以下のような内容です.

バイト数 [値] 説明
1 U8 ピクセル当たりのビット数
1 U8 輝度
1 U8 ビッグエンディアンフラグ
1 U8 トゥルーカラーフラグ
2 U16 赤の最大輝度
2 U16 緑の最大輝度
2 U16 青の最大輝度
1 U8 赤のシフト値
1 U8 緑のシフト値
1 U8 青のシフト値
3 パディング

6.2.2 FixColourMapEntries

このメッセージは現在では存在しません.メッセージタイプ 1として使用されていました.

6.2.3 SetEncodings

サーバーが送信するピクセルデータに使用されるエンコード形式を設定します.このメッセージ中のエンコードタイプの並び順は,優先順位のヒントになります(先頭のエンコード形式が最も優先順位が高い).サーバーはこのヒントを使用しても,使用しなくても構いません.このメッセージを使用してエンコード形式が明示的に指定されなかった場合でも,通常はRaw エンコードを使用して構いません.

純正のエンコード形式に加え,プロトコルに対する特定の拡張をサポートしていることをサーバーに宣言することで,"擬似エンコード形式"を要求することも出来ます.その拡張をサポートしないサーバーはその要求を単純に無視するでしょう.クライアントは,その拡張独自の同意をサーバーから得られない限り,サーバーがその拡張をサポートしていないものと仮定しなければならない点に注意してください.

各エンコード形式の説明は 6.4 を,現時点で使われている擬似エンコード形式の説明は 6.5 を参照してください.

バイト数 [値] 説明
1 U8 1 メッセージタイプ
1 パディング
2 U16 エンコード形式の数

続いて,エンコード形式の数 だけ以下の内容が繰り返されます.

バイト数 [値] 説明
4 U32 エンコードタイプ
0 Row エンコード
1 CopyRect エンコード
2 RRE エンコード
4 CoRRE エンコード
5 Hextile エンコード
16 ZRLE エンコード
0xffffff11 Cursor 擬似エンコード
0xffffff21 DesktopSize 擬似エンコード




その他の登録済みエンコード形式
6,7,8 zlib, tight, zlibhex
0xffffff00 〜 0xffffff10
0xffffff12 〜 0xffffff20
0xffffff22 〜 0xffffffff
tight のオプション

6.2.4 FramebufferUpdateRequest

クライアントが x座標,y座標,幅,高さで指定されるフレームバッファの領域に注目していることをサーバーに通知します.通常,サーバーはこのメッセージに対してFramebufferUpdate で応答します.しかしながら,単独のFramebufferUpdateRequestに対して複数のFramebufferUpdate を返すことも許されていることに注意してください.

サーバーは,クライアントが注目しているフレームバッファのコピーを全て保持していると仮定します.これは,通常サーバーはクライアントに対して増分のみの更新を送れば良いということを意味します.

しかしながら,何らかの理由でクライアントが自分の必要としている領域の内容を失っている場合,FramebufferUpdateRequest増分 にゼロ(false)をセットして送ります.この要求によりサーバーはその領域の完全な内容を可能な限り早く送信します.この領域はCopyRect エンコードを使用して更新されることはないでしょう.

クライアントが自分の注目している領域の内容を失っていない場合,FramebufferUpdateRequest増分 に非ゼロ(true)をセットして送ります.その領域に変更があれば,サーバーはFramebufferUpdate を送信します.FramebufferUpdateRequestFramebufferUpdate との間隔は不定であることに注意してください.

処理速度の速いクライアントの場合,ネットワークの帯域を浪費しないように,増分指定したFramebufferUpdateRequest を送信する割合を調整したいと思うかもしれません.

バイト数 [値] 説明
1 U8 3 メッセージタイプ
1 U8 増分
2 U16 x 座標
2 U16 y 座標
2 U16
2 U16 高さ

6.2.5 KeyEvent

キーが押された,または離されたことを示します.押下フラグ は、キーが押された場合に非ゼロ(true),離された場合にゼロ(false)になります.キー はX Window System で定義されている "keysym" を使って指定されます.

バイト数 [値] 説明
1 U8 4 メッセージタイプ
1 U8 押下フラグ
2 パディング
4 U32 キー

ほとんどの通常キーに対応する "keysym" は、それに対応するASCII値と同じ値です.完全な詳細は,O'Reilly & Associates から出版されている Xlib Reference Manual か,X Window System の <X11/keysymdef.h> を参照してください.その他の一般的なキーの一部は以下の通りです.

キー名称 Keysym 値
BackSpace 0xff08
Tab 0xff09
Return または Enter 0xff0d
Escape 0xff1b
Insert 0xff63
Delete 0xffff
Home 0xff50
End 0xff57
Page Up 0xff55
Page Down 0xff56
Left 0xff51
Up 0xff52
Right 0xff53
Down 0xff54
キー名称 Keysym 値
F1 0xffbe
F2 0xffbf
F3 0xffc0
F4 0xffc1
F12 0xffc9
Shift(左) 0xffe1
Shift(右) 0xffe2
Control(左) 0xffe3
Control(右) 0xffe4
Meta(左) 0xffe7
Meta(右) 0xffe8
Alt(左) 0xffe9
Alt(右) 0xffea

keysym の解釈は複雑です.高い相互運用性を持たせるために,以下のガイドラインに従うべきです.

・"シフト状態"(つまり,どちらかの Shift keysym が押されているかどうか)は,keysym を解釈する際のヒントとしてのみ使用するべきです.例えば,US キーボードで '#' の文字を入力する時にはシフトキーが押されますが,UK キーボードでは押されません.US キーボードを持つサーバーが,UK キーボードのクライアントから '#' の文字を受け取る場合,シフトキーは押されていない状態となります.この場合サーバーは,(例えば '3' ではなく) '#' の文字を取得するために,ローカルシステム上で内部的にシフトキーが押されている"ふりをする"必要があります.

・keysym の大文字・小文字の違いは重要です.これは,これらを同じと見なす一部の X Window System とは異なります.例えば,シフトキーの押されていない大文字'A' の keysym を受け取ったサーバーは,それを'A'であると解釈するべきです.この場合,内部的にシフトキーが押されている"ふりをする"必要があるかもしれません.

・可能なら,サーバーは CapsLock や NumLock のような "lock" keysym を無視するべきです.変わりに,それが大文字か小文字かにより,その文字に基づいた keysym に翻訳するべきです.

・Shift とは異なり,Control や Alt の状態は,他の keysym の意味を変更するものとして扱われるべきです.ctrl + a のようなASCII制御文字には,対応する keysym が存在しないことに注意してください.この場合はビューアによって,Control キーの押下,続いて 'a' の押下として送信されるべきです.

・Control や Alt が文字の keysym を生成するために使われるクライアント上では,その keysym が正しく解釈されるように,余分な"リリース"イベントを送る必要があるかもしれません.例えばドイツ語キーボードでは,ctrl-alt-q は文字 '@' を生成します.クライアントは '@' が正しく解釈されるように,Control と Alt に対する"仮の"リリースイベントを送信する必要があります( ctrl-alt-@ はサーバー上では全く異なる意味を持つでしょう).

・X Window System には「後方タブ」の汎用的な標準はありません.あるシステムでは shift + tab が keysym "ISO_Left_Tab"を生成し,別のシステムではその同じキー操作が独自の keysym "BackTab" を生成します.また別のシステムではそれは"Tab"を生成し,アプリケーションが Shift の状態からそれを前方タブではなく後方タブであると解釈します.RFB プロトコルでは後者のアプローチが好まれます.ビューアは ISO_Left_Tab ではなく,shift + Tab を生成するべきです.しかしながら既存のビューアとの下位互換性を維持するために,サーバーは ISO_Left_Tab も shift + Tab を意味するものと認識するべきです.

6.2.6 PointerEvent

ポインタの移動,またはポインタのボタンが押された・放されたことを示します.ポインタの現在位置は(x座標,y座標 )で表され,ボタン 1 〜 8 の状態はそれぞれボタンマスク の 0 〜 7 の各ビットに対応し,0 が離された状態,1 が押された状態として表されます.

一般的なマウスでは,ボタン 1,2,3 がマウスの左ボタン,右ボタン,中ボタンに対応します.ホイールマウスでは,上方へのホイールスクロールの各ステップがボタン4の押下・開放で表され,下方へのホイールスクロールの各ステップがボタン5の押下・開放で表されます.

バイト数 [値] 説明
1 U8 5 メッセージタイプ
1 U8 ボタンマスク
2 U16 x 座標
2 U16 y 座標

6.2.7 ClientCutText

クライアントが切り取りバッファに新しいASCII文字列を持ったことを示します.行の終端は単一のラインフィード(ASCII値 10)で表されます.キャリッジリターン(ASCII値 13)は必要ありません.

バイト数 [値] 説明
1 U8 6 メッセージタイプ
3 パディング
4 U32 長さ
長さ U8 array 文字列

6.3 サーバーからクライアントへのメッセージ

6.3.1 FramebufferUpdate

フレームバッファ更新は,クライアントがフレームバッファに置くべき,ピクセルデータによる一連の長方形から成ります.このメッセージはクライアントからのFramebufferUpdateRequest に対する応答として送信されます.FramebufferUpdateRequestFramebufferUpdate との間隔は不定であることに注意してください.

バイト数 [値] 説明
1 U8 0 メッセージタイプ
1 パディング
2 U16 長方形の数

この後に長方形の数 だけ,ピクセルデータによる長方形の情報が続きます.各長方形は以下の内容から成ります.

バイト数 [値] 説明
2 U16 x 座標
2 U16 y 座標
2 U16
2 U16 高さ
4 U32 エンコードタイプ
0 Row エンコード
1 CopyRect エンコード
2 RRE エンコード
4 CoRRE エンコード
5 Hextile エンコード
16 ZRLE エンコード
0xffffff11 Cursor 擬似エンコード
0xffffff21 DesktopSize 擬似エンコード

その他の登録済みエンコード形式
6,7,8 zlib, tight, zlibhex
0xffffff00 〜 0xffffff10
0xffffff12 〜 0xffffff20
0xffffff22 〜 0xffffffff
tight のオプション

この後に指定のエンコード形式に従ったピクセルデータが続きます.各エンコードのフォーマットについては 6.4 を,擬似エンコードの意味については 6.5 を参照してください.

6.3.2 SetColourMapEntries

ピクセルフォーマットに"カラーマップ"を使用する場合,このメッセージはクライアントに対して,指定のピクセル値が指定のRGB値にマップされるべきであることを伝えます.

バイト数 [値] 説明
1 U8 1 メッセージタイプ
1 パディング
2 U16 最初の色
2 U16 色の数

この後に色の数 だけ以下の内容が繰り返されます.

バイト数 [値] 説明
2 U16
2 U16
2 U16

6.3.3 Bell

クライアントがベル機能を持っている場合に,ベルを鳴らします.

バイト数 [値] 説明
1 U8 2 メッセージタイプ

6.3.4 ServerCutText

サーバーが切り取りバッファに新しいASCII文字列を持ったことを示します.行の終端は単一のラインフィード(ASCII値 10)で表されます.キャリッジリターン(ASCII値 13)は必要ありません.

バイト数 [値] 説明
1 U8 3 メッセージタイプ
3 パディング
4 U32 長さ
長さ U8 array 文字列

6.4 エンコード形式

6.4.1 Raw エンコード

最も簡単なエンコードタイプが,この Raw ピクセルデータです.データは × 高さ のピクセル値から成ります(高さ は長方形の幅と高さです).値は左から右への順の各ピクセルを表します.全てのRFBクライアントは Raw エンコード形式に対応していなければなりません.また,クライアントから他のエンコード形式を要求されない限り,サーバーはRawエンコード形式だけを提供するべきです.

バイト数 [値] 説明
× 高さ × ピクセル当たりのバイト数 PIXEL array ピクセル

6.4.2 CopyRect エンコード

CopyRect (copy rectangle)エンコードは単純かつ,クライアントが自身のフレームバッファ内の別の場所に既に同じピクセルデータを持っている場合に効率の良いエンコード形式です.このエンコードで送られるデータは単純な X,Y 座標から成り,クライアントがピクセルデータの長方形をコピーすることが出来るフレームバッファ内の位置を示します.これは様々な場面で利用できます.最も分かりやすいのは,ユーザーがスクリーン内でウィンドウを移動した場合や,ウィンドウの内容がスクロールした場合です.それよりは分かり難い利用方法としては,テキスト等の繰り返しパターンの描画を最適化する場合があります.優れたサーバーはあるパターンを一度だけ送信し,フレームバッファ内のそのパターンの位置を知らせることで,その後に続いて現れる同じパターンに対してCopyRect エンコードを使用して送ることが出来るでしょう.

バイト数 [値] 説明
2 U16 コピー元 x 座標
2 U16 コピー元 y 座標

6.4.3 RRE エンコード

RRE はrise-and-run-length encoding を表しており,その名前が暗示していように,本質的に Run-Length エンコードの二次元版の類似方法です.クライアントに届いた RRE でエンコードされた長方形は,グラフィックエンジンの最も単純なものによって即座にかつ効率的に描画することが出来ます.RRE は複雑なデスクトップには適していませんが,いくつかの状況では有用です.

RRE の基になっている思想は,ピクセルデータの長方形をより少さい長方形の領域(それぞれの領域は単一の値のピクセルから成り,それらの結合が元の長方形を形成する)へ分割する,ということです.与えられた長方形をこのような子長方形に,ほぼ最適に分割する計算は比較的簡単です.

このエンコードは背景のピクセル値 Vb(典型的にはその長方形の中で最も広い部分を占めるピクセル値)とカウント N,それ後に N 個の子長方形が続きます.それぞれの子長方形は<v,x,y,w,h>の組から成り,v (≠Vb)がピクセル値,(x,y)が親長方形の左上端からの相対座標,(w,h)が子長方形の幅と高さを表します.クライアントは背景のピクセル値で親長方形を塗りつぶした後,それぞれの子長方形に対応する長方形を塗りつぶしていくことで,元の長方形の領域を描画することが出来ます.

データは以下のヘッダから始まります.

バイト数 [値] 説明
4 U32 子長方形の数
ピクセル当たりのバイト数 PIXEL 背景のピクセル値

その後に子長方形の数 だけ,以下の子長方形の実体が続きます.

バイト数 [値] 説明
ピクセル当たりのバイト数 PIXEL 子長方形のピクセル値
2 U16 x 座標
2 U16 y 座標
2 U16
2 U16 高さ

6.4.4 CoRRE エンコード

注意:CoRRE エンコードにはほとんど利点がありません。Hextile は CoRRE と同じ考え方に基づく,より優れたエンコード形式です.

CoRRE(Compact RRE)は RRE の亜種で,長方形のサイズが最大でも 255 × 255 ピクセルを超えないことを保証しています.これを超える大きさの長方形を送信したい場合,単純に複数のより小さい RFB 長方形に分割して送信します.それぞれの小さい長方形では,その寸法を表すために1バイトだけを使用することが出来ます.典型的なデスクトップにおいて,この方法は RRE よりも高い圧縮率を示します.実際には,さらに制限された大きさの長方形の場合に最良の圧縮率を示しており,現行の実装では最大 48 × 48 のサイズが使用されています.これは,圧縮の効きにくい長方形(典型的にはイメージ情報を含む場合)は Raw で送信され,圧縮の良く効く長方形は CoRRE で送信されるためです.長方形の最大サイズが小さければ小さいほど,この手法における粒度は細かくなります.RRE では,元の長方形全体を RRE か Raw で送信しなければなりません.しかしながら,各 RFB 長方形による一定のオーバーヘッドがあるため,長方形の最大サイズを小さくしすぎること(従って RFB 長方形の数を増加させること)は,圧縮率の低下を招きます.

データは以下のヘッダから始まります.

バイト数 [値] 説明
4 U32 子長方形の数
ピクセル当たりのバイト数 PIXEL 背景のピクセル値

その後に子長方形の数 だけ,以下の子長方形の実体が続きます.

バイト数 [値] 説明
ピクセル当たりのバイト数 PIXEL 子長方形のピクセル値
1 U8 x 座標
1 U8 y 座標
1 U8
1 U8 高さ

6.4.5 Hextile エンコード

Hextile は CoRRE の考え方に基づく亜種です.長方形は 16 × 16 のサイズのタイル に分割されます.子長方形の寸法は各4ピット,計16ビットで表されます.CoRRE とは異なり,各タイルは RFB 長方形ではありません.元の長方形をタイルに分割する際にはあらかじめ決められた方法が取られます.これは各タイルの位置とサイズを明示的に指定する必要がないということを意味します.タイルのエンコードされた内容は,単純にあらかじめ決められた順序で次々と続きます.この順序は左上から始まり,左から右,上から下の順になります。長方形全体の幅が 16 の倍数ではない場合,各行の最後のタイルの幅はその分だけ小さくなります.同じように長方形全体の高さが 16 の倍数ではない場合,最後の行に含まれる全てのタイルの高さが小さくなります.

各タイルは Raw エンコード または RRE に基づく亜種でエンコードされます.前述の通り,各タイルは背景のピクセル値を持ちます.ただし,背景が直前のタイルと同じであれば明示的に指定する必要はありません.全てのタイルが同じピクセル値を持つ場合,タイル全体の前景のピクセル値として一度だけ指定すれば良いことになります.背景と同様,前景のピクセル値も無指定にしておき,前のタイルから値を持ち越すことが出来ます.

データは順番にエンコードされた各タイルから成ります.各タイルは,以下のようなビットから構成されるサブエンコード タイプバイトで始まります.

バイト数 [値] 説明
1 U8 サブエンコードのマスク
1 Raw
2 背景色指定
4 前景色指定
8 子長方形の数
16 子長方形の色の有無

Raw ビットがセットされる場合,他のビットは意味を持たず, × 高さ のピクセル値が続きます(高さ はそのタイルの幅と高さです).Raw ビットがセットされていない場合,マスク内の他のビットの意味は以下の通りです.

背景色指定 - セットされている場合,このタイルの背景色を特定するピクセル値が続きます.

バイト数 [値] 説明
ピクセル当たりのバイト数 PIXEL 背景のピクセル値

長方形内の最初のrawでないタイルでは,このビットを必ず指定しなければなりません.

前景色指定 - セットされている場合,前景色を特定するピクセル値が続きます.このピクセル値はこのタイル内の全ての子長方形に対して使用されます.

バイト数 [値] 説明
ピクセル当たりのバイト数 PIXEL 前景のピクセル値

このビットがセットされている場合,子長方形の色の有無を示すビットはゼロでなければなりません.

子長方形の数 - セットされている場合,子長方形の数を示す以下のような1バイトが続きます.

バイト数 [値] 説明
1 U8 子長方形の数

セットされていない場合,子長方形はありません(つまり,タイル全体の背景が単色ということです).

子長方形の色の有無 - セットされている場合,それぞれの子長方形の前に,その子長方形の色を示すピクセル値が置かれます.

バイト数 [値] 説明
ピクセル当たりのバイト数 PIXEL 子長方形のピクセル値
1 U8 x 座標,y 座標
1 U8 幅と高さ

セットされていない場合,全ての子長方形は同じ色となり,前景色指定のビットがセットされていなければ後のタイルと同じ色になります.子長方形は以下のようになります.

バイト数 [値] 説明
1 U8 xy座標
1 U8 幅と高さ

それぞれの子長方形の座標とサイズは,xy座標幅と高さ の 2 バイトで指定されます.xy座標 の上位4ビットが X座標,下位4ビットが Y座標を表します.幅と高さ の上位4ビットが(幅 - 1),下位4ビットが(高さ - 1)を表します.

6.4.6 ZRLE エンコード

ZRLE は Zlib1 Run-Length Encoding を表しており,zlib 圧縮,タイリング,パレット化,run-length エンコードの組合せです.送信されるデータは4バイトのフィールドで始まり,その後に zlib 圧縮された内容が続きます.一回の RFB プロトコルの接続上では,単一の zlib "stream" オブジェクトが使用されます.したがってZRLE での長方形は,厳密に順番通りにエンコードとデコードが行われなければなりません.

バイト数 [値] 説明
4 U32 長さ
長さ U8 array zlib データ

圧縮されない場合の zlib データ は,左から右,上から下の順の 64 × 64 ピクセルのタイル群という,Hextile に似た形式で表されます.長方形の幅が 64 の倍数ではない場合,各行の最後のタイルの幅はその分だけ小さくなります.同じように長方形全体の高さが 64 の倍数ではない場合,最後の行に含まれる全てのタイルの高さが小さくなります.

ZRLE は新しい型 CPIXEL(compressed pixel) を使用します.これは,トゥルーカラーフラグ が非ゼロ,ピクセル当たりのビット数 が 32,輝度 が24以下,そしてその全てのビットが上位3バイトまたは下位3バイトのどちらかで赤・緑・青の輝度を構成する場合を除き,同意されたピクセル形式のための PIXEL と同じです.この場合 CPIXEL は3バイトのみとなり,下位3バイトまたは上位3バイトを含みます.CPixel当たりのバイト数 は,CPIXEL内のバイト数です.

各タイルはサブエンコード タイプバイトで始まります.このバイトの上位1ビットは run-length エンコードの場合にセットされ,そうでない場合はクリアされます.下位7ビットはパレットのサイズを示し,0 はパレットがないこと,1 はそのタイルが単色であること,2 〜 127 はパレットのサイズを表します.サブエンコード が取り得る値は以下の通りです.

0 - Raw ピクセルデータ. × 高さ のピクセル値が続きます(高さ はそのタイルの幅と高さです).

バイト数 [値] 説明
× 高さ × CPixel当たりのバイト数 CPIXEL array ピクセル

1 - 単色のタイル.ピクセル値が続きます.

バイト数 [値] 説明
Cpixcel当たりのバイト数 CPIXEL ピクセル値

2 〜 16 - パックされたパレットタイプ.パレットサイズ (=サブエンコード) 分のピクセル値から成るパレットが続きます.その後にパックされたピクセルが続きます.各ピクセルはパレットのインデックス(0 が最初のエントリーを意味します)を示すビットフィールドとして表現されます.パレットサイズ が 2 の場合は 1 ビットのフィールドが使用され,パレットサイズ が3または4の場合は2ビットのフィールドが使用され,パレットサイズ が5〜16の場合は4ビットのフィールドが使用されます.これらのビットフィールドはバイト内にパックされ,最上位のビットが最左端のピクセルを表します(つまり,ビッグエンディアンです).ピクセル幅が8,4,2の倍数ではないタイルの場合,各行 が正確にバイト数になるように,アラインメントするためのパディングビットが使用されます.

バイト数 [値] 説明
パレットサイズ × Cpixcel当たりのバイト数 CPIXEL array パレット
m U8 array パックされたピクセル

ここで m は,パックされたピクセルを表現するバイト数で,パレットサイズ が2の場合には floor (( + 7) / 8 ) × 高さ となり,パレットサイズ が 3 または 4 の場合は floor (( + 3) / 4 ) × 高さパレットサイズ が 5 〜 16 の場合は floor (( + 1) / 2) × 高さ となります.

17 〜 127 - 未使用(RLEパレットに対する利点はありません)

128 - 単純な RLE.タイルの終了まで繰り返される run から成ります.run はある行の終端から次の行の始まりまで継続することが許可されています.各 run は,単独のピクセル値と,その run の長さで表されます.長さは1バイト以上で表されます.長さはその長さが表す全てのバイト数より 1 多いものとして計算されます.255 以外の全てのバイト値は最終バイトであることを示します.従って,例えば 1 は[0],255 は[254],256は[255,0],257は[255,1],510は[255,254],511は[255,255,0]などと表されます.

バイト数 [値] 説明
Cpixcel当たりのバイト数 CPIXEL ピクセル値
floor ((runの長さ - 1) / 255) U8 array 255
1 U8 (run の長さ - 1) % 255

129 - 未使用

130 〜 255 - パレットRLE.パレットサイズ = (サブエンコード - 128) 分のピクセル値から成るパレットが続きます.

バイト数 [値] 説明
パレットサイズ × Cpixcel当たりのバイト数 CPIXEL array パレット

その後,単純な RLEと同様,タイルの終了まで run が繰り返されます.長さ 1 の run は,単純にパレットのインデックスを表します.

バイト数 [値] 説明
1 U8 パレットのインデックス

1 バイトより長い run は,最上位ビットがセットされたパレットのインデックスを表し,その後に run の長さが続きます.

バイト数 [値] 説明
1 U8 パレットのインデックス + 128
floor((run の長さ - 1) / 255 U8 array 255
1 U8 (run の長さ - 1) % 255

1参考 http://www.gzip.org/zlib/

6.5 擬似エンコード形式

6.5.1 カーソル 擬似エンコード

カーソル 擬似エンコードを要求するクライアントは,ローカルでマウスカーソルを描画できる能力があることを宣言していることになります.これは低速接続において,かなりの体感速度の向上をもたらします.サーバーは,カーソル 擬似エンコードを用いた擬似長方形を更新の一部として送信することで,カーソルの形状を設定します.この擬似長方形の x 座標と y 座標はカーソルのホットスポットを表し,高さ はカーソルの幅と高さをピクセル単位で表します. ×高さ 分のピクセル値から成るデータの後に,ビットマスクが続きます.このビットマスクは,左から右,上から下への走査線から成り,各走査線は floor (( + 7)/8)のバイト数まで埋められます.各バイト内における各ビットは,対応するカーソル内のピクセルが有効であることを表し,最上位1ビットは最左端のピクセルを表します.

バイト数 [値] 説明
× 高さ × ピクセル当たりのバイト数 PIXEL array カーソルのピクセル
floor(( + 7) / 8) * 高さ U8 array ビットマスク

6.5.2 デスクトップサイズ 擬似エンコード

デスクトップサイズ擬似エンコードを要求するクライアントは,フレームバッファの幅や高さの変更に対応していることを宣言していることになります.サーバーは更新の一部としてデスクトップサイズ エンコードを用いた擬似長方形を送信することで,デスクトップのサイズを変更します.擬似長方形のx 座標y 座標 は無視され,高さ がフレームバッファの新しい幅と高さを表します.この擬似長方形に関連するこれ以上のデータはありません.