view chapter2.tex @ 8:42b6994eac80

update chapter2
author oc
date Tue, 17 Feb 2015 04:17:26 +0900
parents 63ae5aaa2a7a
children
line wrap: on
line source

\chapter{TreeVNC について}


\section{RFBプロトコル}
RFB(remote frame buffer)プロトコル\cite{rfbProtocol}とは、自身の画面を送信し、ネットワーク越しに他者の画面に表示するプロトコルである。
ユーザが居る側をRFBクライアント側と呼び、Framebufferへの更新が行われる側はRFBサーバと呼ぶ。
Framebufferとは、メモリ上に置かれた画像データのことである。
RFBプロトコルでは、最初にプロトコルバージョンの確認や認証が行われる。
その後、クライアントに向けてFramebufferの大きさやデスクトップに付けられた名前などが含まれている初期メッセージが送信される。
RFBサーバ側はFramebufferの更新が行われるたびに、RFBクライアントに対してFramebufferの変更部分だけを送信する。
更にRFBクライアントのFramebufferUpdateRequestが来るとそれに答え返信する。
RFBプロトコルは、描画データに使われるエンコードが多数用意されており、また独自のエンコードを実装することもできるプロトコルである。


\section{TightVNC}
TightVNC(Tight Virtual Network Computing)\cite{tightvnc}はJavaを用いて作成されたRFBプロトコルのクライアントである。
本研究で作成したTreeVNCはTightVNCを元に作成されている。


\section{多人数で VNC を使用するときの問題点}
多人数で従来の VNC を使用する際、1つのコンピュータに多人数が同時につながり、
処理が集中してしまい、性能が大幅に落ちてしまうという問題が生じる。

ゼミ等の画面配信者が頻繁に切り替わる場合、
配信者が替わる度にアプリケーションを終了し、接続をし直さないといけないという問題がある。


\newpage


\section{TreeVNC の構造}
多人数で VNC を用いるために、クライアントの接続がサーバに一極集中してしまう問題を解決する。
そのために、 TreeVNC はサーバへ接続しに来たクライアントをバイナリツリー状に接続する(図\ref{fig:tree})。
バイナリツリーなら、各nodeに最大2台分のクライアントしか接続されない。
$N$台のクライアントが接続しに来た場合、画面配信の画像データをコピーする回数は、
従来の VNC ではサーバ側で$N$回する必要があるが、TreeVNCでは各 node が2回ずつコピーするだけで済む。
TreeVNC は、root への負荷を各 node に分散することにより、処理性能が向上している。

\begin{figure}[htpd]
  \begin{center}
    \includegraphics[scale=0.4]{./images/chapter2/TreeVNC.pdf}
  \end{center}
  \caption{構成される木構造}
  \label{fig:tree}
\end{figure}


\section{Multicast や Broadcast を用いたVNC}

Multicast とは、
同一ネットワーク内でマルチキャストアドレスを持っている端末に対してデータを送信することである。
Broadcast とは、
同一ネットワーク上の全ての端末に対してデータを送信することである。
どちらの通信方法も、root からのデータ送信は1回でよく、
1度送信するとデータの複製はルータが行う。

VNC を Multicast や Broadcast の通信方法を用いて実装すると、
画像データの送信が1度で済み、負荷分散のために木構造を形成する必要もなくなる。

しかし、これらの通信方法でのパケットの扱いには
\begin{itemize}
  \item 送信可能なパケットのブロックサイズが 64000byte までであると決まっている
  \item パケットが途中で消失してしまっても特定することができない
\end{itemize}
といった性質がある。

\newpage

VNC でこれらの通信方法を用いて実装する場合、
パケットの扱いの性質を乗り越えなければならない。

送信可能なパケットのサイズが決まっているので、
画面データは 64000byte 以下に分割し送信しなければならない。
しかし、現在の TreeVNC で用いている方法では、
データ分割の処理には時間がかかってしまう。

パケットの消失を検知するためには、
各パケットに対してシリアル番号を振り分ける。
パケットを受信した node 側で、
シリアル番号が連番で届いているのかどうかを調べれば検知することが可能である。
もし届いていなかった場合は、root に対して再送要求を送信すれば良い。
しかし、Multicast や Broadcast 通信ではパケットロス率が高かった。

これらの通信方法を用いての VNC の実装にはもう少し工夫が必要である。



\section{node 間で行われるメッセージ通信}
RFBプロトコルで提供されているメッセージに加え、 TreeVNC 独自のメッセージを使用している。
TreeVNC で使用されるメッセージの一覧を表\ref{tb:message}に示す。


\begin{table*}[htb]
  \scriptsize
  \begin{tabular}{|l|l|l|} \hline
    通信経路            & message                    & 説明 \\ \hline \hline
                        & FIND\_ROOT                 & 子node接続時にrootを探す。 \\ \cline{2-3}
    send direct message & WHERE\_TO\_CONNECT         & どのnodeに接続すれば良いかを聞く。 \\ \cline{2-3}
    (child to root)     & LOST\_PARENT               & 親nodeの接続が切れた時にrootに知らせる。 \\ \hline

                        & FIND\_ROOT\_REPLY          & FIND\_ROOTへの返信。 \\ \cline{2-3}
    send direct message & CONNECT\_TO                & nodeとnodeの接続をする。 \\ \cline{2-3}
    (root to child)     & CONNECT\_TO\_AS\_LEADER    & 左子nodeとして、nodeとnodeの接続をする。 \\ \hline

    message down tree   & FRAMEBUFFER\_UPDATE        & 画面の差分の画像データ。EncodingTypeを持っている。\\ \cline{2-3}
    (root to child)     & CHECK\_DELAY               & 通信の遅延を測定するmessage。 \\ \hline

    message up tree     & CHECK\_DELAY\_REPLY        & CHECK\_DELAYへの返信。 \\ \cline{2-3}
    (child to root)     & SERVER\_CHANGE\_REQUEST    & 画面切り替えのリクエスト。 \\ \hline

                        & FRAMEBUFFER\_UPDATE\_REPLY & FRAMEBUFFER\_UPDATEのリクエスト。 \\ \cline{2-3}
    send message        & SET\_PIXEL\_FORMAT         & pixel値の設定。 \\ \cline{2-3}
    (root to VNCServer) & SET\_ENCODINGS             & pixelデータのencodeTypeの設定。 \\ \cline{2-3}
                        & KEY\_EVENT                 & キーボードからのイベント。 \\ \cline{2-3}
                        & POINTER\_EVENT             & ポインタからのイベント。 \\ \cline{2-3}
                        & CLIENT\_CUT\_TEXT          & テキストのカットバッファを持った際のmessage。 \\ \hline

                        & FRAMEBUFFER\_UPDATE        & 大本の画面の差分の画像データ。EncodingTypeを持っている。 \\ \cline{2-3}
    send message        & SET\_COLOR\_MAP\_ENTRIES   & 指定されているpixel値にマップするRGB値。 \\ \cline{2-3}
    (VNCServer to root) & BELL                       & ビープ音を鳴らす。 \\ \cline{2-3}
                        & SERVER\_CUT\_TEXT          & サーバがテキストのカットバッファを持った際のmessage。 \\ \hline
  \end{tabular}
  \caption{通信経路とmessage一覧}
  \label{tb:message}
\end{table*}


図\ref{fig:message}は、
TreeVNC で node が root に接続し、画像データを受信するまでのメッセージ通信の様子である。



\newpage


\begin{figure}[htbp]
  \begin{center}
    \begin{tabular}{c}

      \begin{minipage}{0.5\hsize}
        \begin{center}
          \includegraphics[width=67mm]{./images/chapter2/message.pdf}
        \end{center}
        \caption{node 間で行われるメッセージ通信}
        \label{fig:message}
      \end{minipage}

      \begin{minipage}{0.5\hsize}
        \begin{itemize}
          \item nodeはMulticast通信でrootに対してFIND\_ROOTを送信する(1:findRoot())
          \item rootが受信し、FIND\_ROOT\_REPLYを送信する(2:findRootReplay())
          \item node側でどのrootに接続するか選択するパネルが表示される
          \item nodeはパネルでrootを選択し、接続先を要求するWHERE\_TO\_CONNECTを送信する(3:whereToConnect())
          \item 受信したrootはnodeの接続先をCONNECT\_TOで送信する(4:connectTo)
          \item nodeはrootの指定した接続先に接続する
          \item root・node間の接続が確立後、rootからnodeに対して定期的に画像データFRAME\_BUFFER\_UPDATEを送信する(4:framebufferUpdate())
        \end{itemize}
      \end{minipage}

    \end{tabular}
  \end{center}
\end{figure}



\section{配信画面切り替え}
ゼミ等では参加者が順々に発表を行う度に、画面の切り替えが必要となる。
ゼミを円滑に進めるために、この画面の切り替えをスムーズに行う必要がある。

プロジェクタを使用する場合、ケーブルの抜き差しを行わないとならない。
その際に、ディスプレイの解像度の設定をし直す、
接続不良が起こる等の煩わしい問題が生じることがある。

従来のVNCを使用する場合、
画面の切り替えの度に一旦VNCを終了し、発表者のVNCServerへと再接続を行う必要がある。

TreeVNC は、これらの配信者の切り替えの度に生じる問題を解決している。
TreeVNC を立ち上げることで、ケーブルを使用せずに手元のPCに発表者の画面を表示させることができる。
画面の切り替えは、ユーザがVNCSeverへの再接続を行うことなく、切り替えた発表者の画面を取得することができる。

\newpage

TreeVNC の root は配信者の VNCServer と通信を行っており、
VNCServer から画面データを受信し、そのデータを node へと送信している。
画面切り替え用の share button が押されると、
root は share button を押したクライアントの VNCServer と新しく通信をし直す。
これにより、配信者切り替えのために VNC を終了し、再接続する必要がなくなる。

しかし、配信者が変わることで起きる画面サイズの違いや、
マルチディスプレイ全体を表示してしまうことがあるので、
それを解決する必要がある。


\section{MulticastQueue}
配信側の画面が更新されると、 VNCServer から画像データが framebufferUpdate として送られてくる。
TreeVNC は、画像の更新を複数の node に同時に伝えるため、
MulticastQueue という Queue に画像データを格納する。

各 node は MulticastQueue からデータを取得するスレッドを持つ。
node それぞれがデータを取得するため、
MulticastQueue は複数のスレッドから使用される。

MulticastQueue は、CountDownLatch を用いている。
java.util.concurrent.CountDownLatch とは、
java の並列用に用意された API で、他のスレッドで実行中の操作が完了するまで、
複数のスレッドを待機させることのできるクラスである。
スレッドを解放するカウントを設定することができ、
カウントが 0 になるまで await メソッドでスレッドをブロックすることができる。

TreeVNC では、それぞれの画像データにカウントが追加され、
カウントが 0 になると、その画像データは消される。
親 node が接続されている子 node の数だけカウントを設定する。
子 node が画像データを pull すると、そのカウントが減る。
全ての子 node が画像データを pull するとカウントが 0 になり、画像データが消される。

node が MulticastQueue からデータを取得せずに、
Queue にデータが溜まり続け、メモリのオーバーフローが起こる場合がある。
この問題を避けるために、Timeout用のスレッドを用意している。
ある一定時間データが取得されなければ、Timeout を検知し、
取得されなかったデータが全てpollされるという仕組みである。








%\section{オプション一覧}
%${\mathchar`-}$${\mathchar`-}$
%
%\begin{table*}[htb]
%\begin{center}
%  \begin{tabular}{|l|l|} \hline
%    オプション            & 説明 \\ \hline \hline
%    -p                    & a\\ \hline
%    -d                    & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$cui                 & a\\ \hline
%    -v                    & a\\ \hline
%    -version              & a\\ \hline
%    -ns                   & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$fixSize             & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$filterSingleDisplay & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$width               & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$height              & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$host                & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$showTree            & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$checkDelay          & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$addSerialNum        & a\\ \hline
%    ${\mathchar`-}$${\mathchar`-}$logFile             & a\\ \hline
%  \end{tabular}
%  \caption{オプション一覧}
%  \label{tb:option}
%\end{center}
%\end{table*}