VNCプロトコルは
から構成されています。以下の各節では、それぞれのフェーズ、 処理におけるプロトコルの詳細をみていくこととしましょう。
VNCのドキュメントではVNCプロトコルとなっていますが、 プロトコルドキュメント側では旧名のRFB (Remote Framae Buffer)のままになっています。
VNCプロトコルは
から構成されています。以下の各節では、それぞれのフェーズ、 処理におけるプロトコルの詳細をみていくこととしましょう。
VNCのドキュメントではVNCプロトコルとなっていますが、 プロトコルドキュメント側では旧名のRFB (Remote Framae Buffer)のままになっています。
VNCセッションはTCPを使用し、ビューワ(クライアント)からの コネクションで始まります。
VNCプロトコルではコネクションが確立したなら 最初にプロトコルバージョンメッセージを交換します。 プロトコルバージョンメッセージは12バイトのASCII文字列で
'RFB xxx.yyy\n'
の形式です。ここでxxx、yyyはそれぞれプロトコルの メージャー、マイナーバージョンを示します。
コネクションが確立したなら最初にサーバが 自分のサポートするプロトコルバージョンを通知します。 ビューワはこのメッセージによって接続先が 確かにVNCサーバであること、 およびそのバージョンを確認します。 通知されたバージョンが利用可能であればビューワは、 自分の側のプロトコルバージョンをサーバに返します。
このようなバージョン番号の交換は、サーバ、クライアントの双方で ある程度のバックワードコンパチビリティを持てるようにするためのものです。 現在のところは、 マイナーバージョンについてのみコードが実装されています。
プロトコルバージョンの交換後、 サーバはクライアントに認証方式を通知します。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | 認証方式 | |
0 | 接続失敗 | ||
1 | 認証無し | ||
2 | VNC認証 |
後続のデータは指示された認証方式によって異なります。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | 理由の長さ | |
理由の長さ | CARD8 array | 理由の文字列 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
16 | CARD8 | チャレンジ |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
16 | CARD8 | 応答 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | 応答 | |
0 | OK | ||
1 | 失敗 | ||
2 | 多すぎる |
認証されたならクライアントは次の初期化メッセージを送ります。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 共有フラグ |
共有フラグは、クライアントがリモートデスクトップを 他のクライアントと共有するかどうかを指示するものです。 このフラグをセットすれば、 同じデスクトップを複数のビューワで 同時にアクセスすることができます。
しかし、最新のサーバには、この指定を無視して、常に共有、 常に占有を指示するオプションが追加されています。
クライアント初期化メッセージを受け取ると サーバはサーバ初期化メッセージを返します。 これはリモートデスクトップのサイズ、 ピクセル形式、名前を通知するものです。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
2 | CARD16 | 画面の幅 | |
2 | CARD16 | 画面の高さ | |
16 | PIXEL_FORMAT | サーバ側のピクセル形式 | |
4 | CARD32 | 名前の長さ | |
名前の長さ | CARD8 array | 名前の文字列 |
名前はリモートデスクトップを識別するためのもので、 Xvncサーバの場合にはユーザ名、 WinVNCの場合にはマシン名を元に設定されます。 クライアント側での使い方は特に規定されていません。 多くの場合ビューワのタイトルとして表示されています。
ピクセル形式は以下のデータで指示されます。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | ピクセルビット数(転送上) | |
1 | CARD8 | ピクセルビット数(実データ) | |
1 | CARD8 | ビッグエンディアンフラグ | |
1 | CARD8 | true-color フラグ | |
2 | CARD16 | R 最大値 | |
2 | CARD16 | G 最大値 | |
2 | CARD16 | B 最大値 | |
1 | CARD8 | R シフト | |
1 | CARD8 | G シフト | |
1 | CARD8 | B シフト | |
3 | パディング |
転送上のビット数は、8、16、32 のいずれかでなければなりません。 実データのビット数は、転送上されたピクセルデータの内、 どれだけが実際のデータになるのかを示します。
true-colorの場合には、後続の6データでRGBの表現形式を指示します。 これはピクセルデータをエンディアンフラグの指示によって 整数値とした場合、RGBそれぞれの最大値と、 フィールド位置を指示するものです。
例えば下記のBGR233形式(1)を使う場合には
となります。
プロトコル上は(true-colorフラグをオフにすることによって) pseudo-colorを使うようにすることもできます。 その場合は、後続のデータは無視され、 (後述の)カラーマップの設定、変更によって カラーマップを設定します。 しかし、現時点ではpseudo-colorが ちゃんと使えるサーバは存在していないようです。
サーバの初期化メッセージで通知されたサーバ側のピクセル形式に対して、 クライアントは以降自分で受け取りたいピクセル形式を通知します。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 0 | メッセージタイプ |
3 | パディング | ||
16 | PIXEL_FORMAT | ピクセル形式 |
プロトコルの定義上は、これは初期化用のメッセージではなく、 クライアントが自由に要求できるメッセージとされています。 しかし、画面データはこのメッセージで指示するピクセルビット数に 強く依存した形式で転送されてきます。 しかし、画面データには それがどのようなビット数のものかを特定する情報がありません。 このためセッションの途中でビット数を変更すると、 それ以降のデータを確実に解釈できる保証はありません。 このため多くの実装では初期化時に一回だけ通知するようにしています。
セッション途中で変更できるようになっているのは Windows用のビューワだけです。 そこでは変更指示を送る前に、 古い形式での画面データの通知が完了するようにディレイを入れています。 これは大抵の場合、ちゃんと動作しますが、 完全に動作する保証はありません。(2)
クライアントは更に 自分が受け取ることのできる矩形エンコーディングの形式を通知します。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 2 | メッセージタイプ |
3 | パディング | ||
2 | CARD16 | エンコーディング数 | |
4×数 | CARD32 array | エンコーディングのリスト |
これもプロトコル定義上は初期化メッセージではなく クライアントが自由に送出できるメッセージです。 ただしこれについては 画面データにエンコーディングタイプが記載されていますので、 実際にセッションの途中で変更しても問題はありません。 しかし、多くのビューワでは初期化時に一回だけ通知しています。
エンコーディングは以下の5種類で、 先にリストされたものが優先されます。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | エンコーディングの種類 | |
0 | Raw | ||
1 | Copy Rectangle | ||
2 | RRE | ||
4 | CoRRE | ||
5 | hextile |
指示されていなくてもRawエンコーディングは無条件に有効になります。 それぞれのエンコーディングの方法については 画面データの通知のところで説明します。
クライアント側で発生した入力イベントはキーイベント、 マウスイベントとしてサーバに通知されます。 実際にはキーやマウス以外のイベント(ペン、メニュー等)を これらにマッピングして送ることもできます。
キーイベントは以下のメッセージでサーバに通知されます。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 4 | メッセージタイプ |
1 | CARD8 | ダウンフラグ | |
2 | パディング | ||
4 | CARD32 | キーコード |
キーコードにはXのkeysymdeef.hの値を使います。
このため、XvncとXビューワとの組み合わせにおいては、 どのようなキーでも確実に通知されます。 しかしその他の組み合わせの場合にはサーバ、クライアントの いずれかで変換が必要になります。 これらの変換ではkeysymdef.h のすべてのキーを サポートしているわけではありませんので、 一部のキー(NLSキーなど)が通知されないことがあります。 実際、WinVNCでは日本語変換関連のキーはまったく動作しません。
マウスイベントは以下のメッセージでサーバに通知されます。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 5 | メッセージタイプ |
1 | CARD8 | ボタンマスク | |
2 | CARD16 | x座標 | |
2 | CARD16 | y座標 |
これによってマウスの移動とボタンの状態がサーバに通知されます。 ボタンマスクは0-7の各ビットがボタン1-8の状態
0 : | ボタンは押されていない |
1 : | ボタンは押されている |
を示します。
ボタン数の差はビューワで吸収する必要があります。 古いWindows版ビューワでは右ボタンを2/3に切り替えて 使うようになっていましたが、最新版では 同時押下によるセンターボタンエミュレーションが追加されました。
画面の通知は、クライアントからの通知要求と、 それに対して返されるサーバからの画面更新データとから構成されます。 なお、これらは一対一に対応するものではなく、 ひとつの通知要求に対して複数の画面更新データが返されることもあれば、 複数の通知要求に対する画面更新データがマージされて返されることもあります。 実装上、画面更新データは通知要求とは独立したものとして扱う必要があります。
リモートデスクトップの画面が必要な場合、 クライアントは以下のメッセージでサーバにデータの通知を要求します。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 3 | メッセージタイプ |
1 | CARD8 | インクリメンタル | |
2 | CARD16 | x座標 | |
2 | CARD16 | y座標 | |
2 | CARD16 | 幅 | |
2 | CARD16 | 高さ |
このメッセージはリモートデスクトップの座標、幅、高さで指示される 矩形領域の画面データを送るようにサーバに要求するものです。 インクリメンタルフラグがセットされた場合には 以前に要求した時点以降に更新された画面データだけが通知されます。
多くのビューワでは、最初に全画面データを要求し、 以降インクリメンタルフラグをセットして、 全画面上の更新された部分のみの画面データを要求します。 これらの場合、対象となる矩形領域はいつも リモートデスクトップの全体になります。
しかし、ビューワ側の処理の都合で 一部の画面データが失われるような場合 (画面イメージをキャッシュしないでスクロールするようなケース)には、 失われた範囲だけを対象として通知要求を発行すると、 無駄なく画面イメージを取得することができるわけです。
サーバからの画面更新データは矩形データの列として通知されてきます。 画面データの先頭にはメッセージのタイプと 後続する矩形データの数が記録されています。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 0 | メッセージタイプ |
1 | パディング | ||
2 | CARD16 | 矩形の数 |
この後に指示された数の矩形データが続きます。 各々の矩形データの先頭には以下のヘッダ情報が記載されています。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
2 | CARD16 | x座標 | |
2 | CARD16 | y座標 | |
2 | CARD16 | 幅 | |
2 | CARD16 | 高さ | |
4 | CARD32 | エンコーディング形式 | |
0 | Raw | ||
1 | Copy Rectangle | ||
2 | RRE | ||
4 | CoRRE | ||
5 | hextile |
ヘッダに続く矩形データはエンコーディング形式によって異なります。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
2 | CARD16 | x座標 | |
2 | CARD16 | y座標 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | サブ矩形の数 | |
n | ピクセル値 | 背景色 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
n | ピクセル値 | サブ矩形の色 | |
2 | CARD16 | x座標 | |
2 | CARD16 | y座標 | |
2 | CARD16 | 幅 | |
2 | CARD16 | 高さ |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
4 | CARD32 | サブ矩形の数 | |
n | ピクセル値 | 背景色 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
n | ピクセル値 | サブ矩形の色 | |
1 | CARD8 | x座標 | |
1 | CARD8 | y座標 | |
1 | CARD8 | 幅 | |
1 | CARD8 | 高さ |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | サブエンコーディングマスク | |
1 | Raw | ||
2 | 背景色有り | ||
4 | 前景色有り | ||
8 | サブ矩形有り | ||
16 | 色付き |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
n | ピクセル値 | 背景色 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
n | ピクセル値 | 前景色 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | サブ矩形数 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
n | ピクセル値 | サブ矩形の色 | |
1 | CARD8 | x,y座標 | |
1 | CARD8 | 幅、高さ |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | x,y座標 | |
1 | CARD8 | 幅、高さ |
プロトコル上はサーバとクライアント間で クリップボード上のデータを交換することができるようになっています。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 3 | メッセージタイプ |
1 | パディング | ||
4 | CARD32 | 長さ | |
長さ | CARD8 array | テキスト |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 6 | メッセージタイプ |
1 | パディング | ||
4 | CARD32 | 長さ | |
長さ | CARD8 array | テキスト |
改行は'\n'で表現することになっています。 ただ、日本語を使う場合のエンコードについては (あたりまえですが)規定されていません。 同じコード系であれば問題無く転送できますが、 コード系が異なっていると役に立ちません。
サーバからクライアントにベルを通知することができます。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 2 | メッセージタイプ |
これをどのように扱うかはビューワに依存します。 多くのビューワでは、このメッセージ受信で、 最小化されていたウィンドウをリストアすることもできるようになっています。
これは、pseudo-colorを使う場合に使用されるものです。
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 1 | メッセージタイプ |
1 | パディング | ||
2 | CARD16 | 先頭の色インデックス | |
2 | CARD16 | 色の数 |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
2 | CARD16 | R | |
2 | CARD16 | G | |
2 | CARD16 | B |
バイト数 | 型 | 値 | 意味 |
---|---|---|---|
1 | CARD8 | 2 | メッセージタイプ |
1 | パディング | ||
2 | CARD16 | 先頭の色インデックス | |
2 | CARD16 | 色の数 |
ですが、現在のところpseudo-colorがサポートされているサーバは 存在していないので使うことはまずないでしょう。