view presen/prosym.md @ 29:ce0aff4548a1

Update
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Thu, 07 Jan 2016 10:47:34 +0900
parents c9641abe2163
children 57b34ffe2971
line wrap: on
line source

title: 有線 LAN 上のPC画面配信システムTreeVNCの改良
author: Tatsuki IHA
profile:
lang: Japanese
code-engine: coderay

# 画面共有を利用したコミュニケーション
授業やゼミ等で、それぞれが PC 端末を持っている場合では、PC の機能を活かした コミュニケーションが可能である。教員が操作する画面をそのまま学生に配信したり, ゼミ などで、発表する学生の画面を切り替えたりすることを可能にしたい。画面配信システム TreeVNC は参加したクライアントをバイナリツリー状に接続し、配信コストを分散させる 仕組みを取っている。そのため, 多人数が参加しても処理性能が下がらない。また、ツリー のルートが参照している VNC サーバーを変更することで、ケーブルの差し替えなしに画面 の切替が可能となる。


# 問題点
しかし、 TreeVNC を実際に使用していく中で様々な問題が発生した。
本研究では TreeVNC の改良として、複数のネットワークへの対応、 WAN への対応、 マルチディスプレイへの対応を行うとともに、TreeVNC 有用性を示すために画像データの遅延時間計測を行った。

# 問題:複数のネットワーク
- 琉球大学では無線と有線が別々のネットワークになっている
- TreeVNCは単一のネットワークにしか対応できず、両方のネットワークにつながっている端末でも1つのネットワークでしか使用できなかった

# 問題:マルチディスプレイ
- ゼミ等で発表者毎に画面切り替えを行う際、デュアルディスプレイを使っている人がいた
- その際 VNC サーバーからはすべての画面データが送信されており、発表とは関係ない画面も配信されていた

# 問題:WANへの対応
- 講義等を大学外の遠隔地から受けたい場合がある
- TreeVNC は NAT を超えた接続が行うことができない

# この発表は
- TreeVNC の概要
- 今回の改良
- TreeVNC の評価

# TreeVNC
-  TreeVNC は本研究室で開発している VNC を利用した画面配信システム
- 参加したクライアントをバイナリツリー状で接続することで配信コストを分散させる
- スムーズな画面の切替を行う

# VNC
- VNC(Virtual Network Computing) は RFBプロトコルを用いて遠隔操作を行うソフトウェア
- サーバー側とクライアント側に分かれており、サーバーを起動し、クライアントがサーバーに接続を行うことで遠隔操作を可能とする

# RFB プロトコル
- RFB(Remote Frame Buffer)プロトコルは VNC で用いられているプロトコル
- 自身の画面をネットワーク越しに他者の画面に表示する
- RFB サーバと RFB クライアントに分かれている
- Framebuffer と呼ばれるメモリ上に置かれた画像データを使用して画面表示を行う
- RFB サーバーは Framebuffer が更新されるたびにRFB クライアントに対して Framebuffer の変更部分だけを送信する。

# 多人数でVNCを使用する際の問題点
- 多人数のクライアントが1つのサーバーに接続する構造である
- そのため、サーバー側の処理性能が落ちてしまう
- ゼミ等の発表で画面配信者が切り替わる場合配信者が変わるたびにアプリケーションを終了し、再接続を行う必要がある。

# TreeVNC の構造
- Java で作成されたTightVNC(Tight Virtual Network Computing) を元に作成されている
- クライアント同士をバイナリツリー状に接続する
- バイナリツリーのルートのノードをRoot Nodeと呼び、 Root Node に接続されるノードを Node と呼ぶ
- Node は 親 Node から送られたデータを自分の子 Node に流す機能、 逆に子 Node から送られてきたデータを親 Nodeに流す機能がある
<img src="./images/TreeVNC.svg" alt="message" width="400">

# Root Node
- Root Node は 子 Nodeにデータを流す機能に加え 
    - 各 Node の管理
    - VNC サーバーから送信されたFramebuffer の管理を行う

# TreeVNCの通信量
- ポート一本あたりの負荷
    - 従来のVNC : Node数 * データ量
    - TreeVNC   : (2(子供の数) + 1) * データ量
- 従来のVNCはNode数に比例
- TreeVNCは子供の数に関係するためNode数に関係なく一定

# TreeVNC の圧縮形式
- TreeVNC は ZRLEE というエンコードでデータのやり取りを行う
- ZRLEE は ZRLE を元に生成される

# ZRLE
- RFB プロトコルで使えるエンコーディングタイプの1つ
- Zlib で圧縮されたデータとそのデータのバイト数がヘッダーとして付け加えられる
- java.util.zip.deflater で圧縮, java.util.zip.inflater で解凍が行える

# java.util.zip.deflater の問題点
- java.util.zip.deflater は必要な辞書を書き出す事ができない
- そのためZlibで圧縮されたデータを途中から受け取ってもデータを正しく解凍できない

<img src="./images/ZRLE.svg" alt="message" width="800">

# ZRLEE
- ZRLEE はZRLE を一度 Root Node で解凍して再圧縮を行う 
- 再圧縮の際にfinish()を入れることで初めからデータを呼んでいなくても解凍を行える
- 一度 ZRLEE に変換すれば子 Node はそのデータをそのまま流すだけで良い

<img src="./images/ZRLEE.svg" alt="message" width="400">

# TreeVNC の通信経路
- ある Node から Root Node に直接通信を行う send direct message (Node to Root)
- Root Node からある Node に直接通信を行う send direct message (Root to Node)
- Root Node から木の末端の Node までのすべての Node に通信を行う messeage down tree (Root to Node)
- ある Node から木構造を上に辿って Root Node まで通信を行う message up tree (Node to Root)
- Root Node から配信者の VNC サーバーへ の通信を行う send message (Root to VNC- Server)
- VNC サーバーから Root Node への通信を行う send message (VNCServer to Root)

# TreeVNC に参加するまでのメッセージ通信の流れ
<table>
  <tbody>
    <tr>
      <td><img src="./images/message.svg" alt="message" width="300"/></td>
      <td> 
        <ul>
          <li>接続を行う Node(以下 Client Node) は Multicast 通信で Root Node に対して FIND_ROOT を送信する(1:findRoot())</li>
          <li>Root Node が FIND_ROOT を受信すると接続を行う Node に FIND_ROOT_REPLY を送信する (2:findRootReplay)</li>
          <li>Client Node 側で、どの Root Node に接続するかを選択するパネルが表示される</li>
          <li>Client Node はパネルで接続する Root Node を選択し、Root に対して接続先を要求 する WHERE_TO_CONNECT を送信する (3:whereToConnect())</li>
          <li>受信した Root Node は Client Node の接続先を CONNECT_TO で送信する (4:connectTo)</li>
          <li>Client Node は Root の指定した接続先に接続しに行く</li>
          <li>Root Node, Client Node 間の接続が確立後 Root Node から Clinet Node に対して定期的に画像データ FRAME_BUFFER_UPDATE を送信する (5:framebufferUpdate())
          </li>
        </ul>
      </td>
    </tr>
  </tbody>
</table>

# 切断時の木の再構成
- TreeVNC はバイナリーツリーという特性上 Node の切断を検知できずにいると、Node 同士で構成された木構造が崩れてしまい、 木構造が崩れた状態で新しい Node が接続に来た場合に適切な場所に Node を接続することができない
- 木構造のネットワークトポロジーは Root Node  が持っている nodeList というリストで管理している
- Nodeの接続が切れた場合、木の再構成を行うため nodeListを更新する必要がある

# 切断時の木の再構成
- TreeVNC は Node 切断の検知を LOST\_CHILD というメッセージ通信で行っている
- LOST\_CHILD の検出方法は MulticastQueue という画像データを蓄積するキューを利用して行う
- 子 Node は 親 の MulticastQueue から画像データを取得し、画面を描画する
- 一定時間 MulticastQueue から画像データが取得されない場合 Memory Over Flow を回避するためにTimeout スレッドが用意されている
- Timeout を検知した際、子 Node との接続が切れたと判断し、木を再構成する

# LOST_CHILDの例
- 子 Node の切断を検知した Node が Root Node へ LOST\_CHILD メッセージを送信する (1:lostChild())
- LOST\_CHILD メッセージを受け取った Root Node は nodeList の更新を行う (2:updateNodeList())
- 切断した Node を nodeList から消し、 nodeList の最後尾の Node に切断した node number を割り当てる
- Root Node は最後尾の Node に、切断した子 Node が接続していた親 Node に接続する様 に CONNECT\_TO メッセージを送信する (3:connectTo(1))
- 最後尾の Node が子 Node を失った親 Node へ 接続しに行く (4:connectToParent(1))
<img src="./images/lostChild1.svg" alt="message" width="800">

# 共有画面切り替え
- TreeVNC の Root Node は配信者の VNC サーバーと通信を行っている
- 画面を配信されている側のビューワにある Share Screen ボタンが押されると木をたどり、 Root Node に SERVER\_CHANGE\_REQUEST メッセージを送信する
- Root Node は Share Screen ボタンを押したクライアントの VNC サーバーと通信を始める。
- そのため TreeVNC は配信者切り替えの度にVNCを終了し、再接続する必要がない。

# QUALITY モードと SPEED モード
- 高解像度のデータの描画処理はPCのスペックによって重くなる場合がある
- 画像描画処理には
    - 高画質優先の QUALITY モード
    - 描画速度優先の SPEED モード
- 今まで QUALITY モード を使用していた(変更不可)
- 今回ビューワからユーザーがどちらのモードを使用するかを変更できるようにした
- これにより描画処理の遅延が解決できると思われる

# マルチディスプレイ
- VNC サーバーからはすべての画面データが送信されてしまっていた
- 共有したいディスプレイを選択して共有するのが望ましい
- 画面切り替えの際のSERVER\_CHANGE\_REQUESTに共有するディスプレイの座標を付加する
- Root Node は 接続した VNC サーバーから画像データを要求する FRAME\_BUFFER\_UPDATE\_REQUEST メッセージに受け取った座標を付加する
- VNC サーバーは要求された座標内の画像データを FRAME\_BUFFER\_UPDATE メッセージで Root Node に送信する
<img src="./images/shareScreenToMultiDisplay.svg" alt="message" width="800">

# 複数ネットワークの対応
- 従来の TreeVNC はクライアントの接続する木構造が単一であった
- Root Node が複数のネットワークに接続していても単一のネットワークでしか使用することができない
- Root Node が接続しているネットワークごとに木構造を形成する
- Root Node は TreeManager というオブジェクトで接続部分を管理している(nodeListもそこで生成される)
- TreeManager を保持しているネットワーク毎に生成する
- 新しい Node が接続してきた際、 interfaces から Node のネットワークと一致する TreeManager を取得し、 接続の処理を任せる
<img src="./images/MultiNetworkTree.svg" alt="message" width="800">

# WANへの対応
- NATを超えたネットワークからの接続は直接配信側の Root Node に 接続を行うことで実現する
- この接続を Direct Connection と呼ぶ
- Direct Connection した Node はそのネットワークの Root Node になり、そのネットワークの他の Node は Root Node に接続を行い木構造を作る
- 配信側の Root Node は Direct Connection で接続された Root Node に対して 画像データ (Framebuffer) を送信する
- 画像データを受け取った Root Node は 接続されている子 Node に対して画像データを送信する
<img src="./images/directConnection.svg" alt="message" width="800">

# TreeVNCの評価
- 木の深さによる画像データの遅延を調べる
- 実験環境
    - 実際に講義を受講している学生が TreeVNC を使用
    - 約20名の接続

# 使用するメッセージ
- 計測用のメッセージとして CHECK\_DELAY , CHECK\_DELAY\_REPLY を追加
    - CHECK\_DELAY は 送信時間と画像データ 
        - Root Node から 末端の Node に伝達する
    - CHECK\_DELAY_REPLY は画像サイズとCHECK\_DELAY で受け取った送信時間
        - 各 Node から Root Node まで伝達する

# 実測方法
- まず Root Node は CHECK\_DELAY を 末端 Node まで各 Node を伝いながら伝達する
- CHECK\_DELAY を受け取った各 Node は CHECK\_DELAY\_REPLY を送信する
- CHECK\_DELAY\_REPLY を受け取った Root Node は CHECK\_DELAY の送信にどれだけ時間がかかったかの計算を行う

```java
// 遅延時間の計算
Long delay = System.currentTimeMillis() - time;
```

# 結果
<img src="./images/depth1.svg" alt="message" width="800">
<img src="./images/depth2.svg" alt="message" width="800">
<img src="./images/depth3.svg" alt="message" width="800">
<img src="./images/depth4.svg" alt="message" width="800">

- 画像データの伝達はほぼ1秒以内に収まっているが、容量が小さい場合でも時間がかかる場合がある。 それはその送信の前に大容量の画像を送信した後の回線の Delay が残っているためだと考えられる
- 深さ 3 で極端に遅い場合がある。 遅い原因として1つの Node がボトルネックになっている事が判明した。
- ネックになった Node をそのままにするとその子Nodeに影響を及ぼしてしまう。 そのためその Node に何らかの対応を行う必要がある

# まとめと課題
- 今回TreeVNCの様々な問題点の解決を行った
- 実験を行うことにより、さらなる問題点が判明した

- 実測で判明したネックになっているNodeへの対処
- WAN での 画面切り替え
- 追加した機能の評価方法を思考し、評価を行う