Java による授業向け画面共有システムの設計と実装
大城 信康 谷成 雄
目的と背景
大学の講義中、スクリーンに映されている画面は後ろの席程見えずらい。
その問題を手元のPCにも写せるようにすることで解決しようと考えた。
60人以上での画面共有を行うことを目標とする。
VNCを用いての画面共有
画面を共有する方法 -> VNC
VNC: Virtual Network Computing ネットワークを介してコンピュータを遠隔操作するプログラム
VNCのリモートPCの画面を写す機能を利用する。
通常のVNCの問題点
|
VNC Serverの負荷が重い。
Server側の通信網1本への通信負荷が高い。
|
通常のVNCの問題点
1台と48台でVNCをかけた時のスループットとサーバ側のCPU使用率
|
スループット(単位:Byte) |
CPU使用率 |
1台 |
20M |
15% |
48台 |
0.4M |
100% |
VNCに使われるCPUの使用率が100%になり、スループットが5分の1まで下がっている。
VNCの問題点の解決策
クライアントを木構造で接続させる
TreeVNCの利点
通常のVNC |
TreeVNC |
|
|
クライアントが増えてもかかる負荷一定。
通信網1本に対する負荷が減り、安定した通信ができる(有線)。
TreeVNCの利点
通常のVNC |
TreeVNC |
|
|
|
通常のVNC |
TreeVNC |
最大負荷 |
N * データ量 (クライアントの数に比例) |
(M+1) * データ量 |
クライアントの数をN、木構造の子供の数をMとする
TreeVNCの設計
TreeVNCのクライアントは最初にTop Proxyに接続を行う。
データは木の下へと流れていく。
tightVNC ViewerのJava版(ver 1.3)を元にTreeVNCの実装を行う。
発表内容
- RFB Protocol
- データ転送量
- データ転送に用いたMulticastQueueについての説明
- TreeVNCのデモ
- 木構造の再構築
- ZRLE Encodingの問題
RFB protocol
Remote Frame Buffer Protocol :
GUI操作によるリモートアクセス用の通信プロトコル。VNCで用いられる。
転送される画面(フレームバッファ)のデータは変更があった部分(差分)だけが矩形単位で送られる。
□ で囲まれている矩形のデータだけが送られてくる。
VNC のシーケンス図
|
1~5まではinitial seaquenceとなる。
6以降は繰り返し行われる処理。画面のデータが転送されてくる。
|
RFB Protocol
FramebufferUpdateRequest:
画面に差分が発生したらサーバから教えて貰うためのリクエスト
バイト数 |
型 [値] |
説明 |
1 |
U8 3 |
message-type |
1 |
U8 |
incremental |
2 |
U16 |
x-position |
2 |
U16 |
y-position |
2 |
U16 |
width |
2 |
U16 |
height |
|
このリクエストはTop Proxyだけが行う。
RFB Protocol
FramebufferUpdate: 画面の更新データ
バイト数 |
型 [値] |
説明 |
1 |
U8 0 |
message-type |
1 |
U8 |
padding |
2 |
U16 |
number-of-rectangles |
以下number-of-rectanglesの数だけ矩形のデータが続く
バイト数 |
型 |
説明 |
2 |
U16 |
x-position |
2 |
U16 |
y-position |
2 |
U16 |
width |
2 |
U16 |
height |
4 |
U32 |
encoding-type |
... |
... |
PIXEL DATA |
|
|
RFB Protocol
例:FramebufferUpdate
x-position |
336 |
y-position |
388 |
width |
724 |
height |
449 |
encoding-type |
16(ZRLE) |
ZRLE |
... |
データ転送量
矩形の大きさと描画に必要なデータ量(単位:Byte)
矩形の大きさ \ エンコード |
RAW |
ZRLE |
724 * 449 |
1.3M |
0.8M |
1920 * 64 |
0.5M |
0.15M |
1920 * 1080 |
8.2M |
3.4M |
RAW、ZRLE、ZRLEEエンコードのデータ量の比較
データ転送量
クライアントが60台の時の通常のVNCと、2分木構成にしたTreeVNCの通信網への負荷について考える。
|
通常のVNC |
TreeVNC |
最大負荷 |
N * データ量(クライアントの数に比例) |
(M+1) * データ量 |
クライアントの数をN、木構造の子供の数をMとする
N = 60、 M = 1 となる。
724 * 449 の画面分のデータ(0.8M)を送信するとする。
データ転送量
|
通常のVNC |
TreeVNC |
最大負荷 |
48M |
2.4M |
通常のVNC |
TreeVNC |
|
|
クライアント:60台 TreeVNCは2分木でTreeを構成
エンコード
MacintoshでVNCを行うとZRLEを使うことができる。
データ量がRAWデータの約4分の1のデータ量ですむ。
TreeVNCではこのZRLEを扱っている。
ZRLE
ZRLE : Zlib Run-Length Encoding
- Zlib圧縮(gzip)されたデータ扱うエンコーディング。
最初の4バイトにはZlibのデータの長さが、続いてZlibのデータが送られてくる。
バイト数 |
型 |
説明 |
4 |
U32 |
length |
length |
U8 array |
zlibData |
Zlibデータ
辞書がなければデータを正しく解凍できない
ZRLEの問題
辞書はZlibデータの最初に送られてくる。
ZRLEのデータを最初から送ることができれば、辞書も送ることができる。
データの途中から送ると辞書は送られず、正しく解凍を行うことができない。
ZRLEE
そこで、Top ProxyにZRLEのデータを再度圧縮し直すことで辞書を付けてもらうことにした。以下はその部分のソースである。
Deflater nDeflater = deflater; // new Deflater();
LinkedList out = new LinkedList();
unzip(inflater, inputs, 0 , out, INFLATE_BUFSIZE);
// dump32(inputs);
int len2 = zip(nDeflater, out, 0, bufs);
一度再圧縮してしまえば後はどこからデータを流しても問題ない。
ZRLEE
クライアント側は毎回新しいZRLEのストリームを使うようにする。
if (rfb.updateRectEncoding==RfbProto.EncodingZRLEE)
zrleInStream = null;
if (zrleInStream == null)
zrleInStream = new ZlibInStream();
JavaではZlibの辞書を取り出す機能がなかった為、このような方法をとることになった。
MulticastQueue
MulticastQueueはjava.util.CountDownLatchを用いて実装されたクラスである。
クライアントから接続されると、データ転送用のスレッド(sender)が走る。
このスレッドは次に流すデータが来るまでは待機して置かなければならない。そして流すべきデータがくるとまた動き始めなければならない。
このスレッドの待機・解放を行うのがMulticastQueueとなる。
MulticastQueue
MulticastQueueの図を入れる。
接続されてきた時点からデータの送信が始まる。データは読み込まれるまでメモリ上に残っている。
MulticastQueueの問題点
Clientがデータを読み込まないとデータが溜まりメモリを圧迫してしまう。
MulticastQueueの問題点
解決策
TimeOut(TO)スレッドを走らせ、一定の時間データを読み込まなければ代わりにこのTOが読み込むようにする。
TreeVNCのデモ
では実際に動かしてみる。
TreeVNCの利点と欠点
- ケーブル1本への負荷が減る。一極集中型よりスループットを維持できる。
- 無線を使われると遅くなる。
テスト環境について
CUI版のVNCクライアントを作成
48台あるクラスタでCUI版のクライアントをはしらせてVNCをかけさせる。
最初の1台目と50台めをGUI版のクライアントで接続を行い見比べてみる。
既存のプログラムとの比較
VNC Reflector
- tightVNCの作者が作成したプログラム
- VNC Reflecotrにクライアントが接続することでVNCを行うことができる