changeset 3:8a9c3d23ca4a

write chapter4
author Yu Taninari <e085734@ie.u-ryukyu.ac.jp>
date Wed, 15 Feb 2012 00:16:16 +0900
parents 093d4644d7ee
children 15208c6d806d
files paper/chapter4.tex
diffstat 1 files changed, 109 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/paper/chapter4.tex	Tue Feb 14 23:25:41 2012 +0900
+++ b/paper/chapter4.tex	Wed Feb 15 00:16:16 2012 +0900
@@ -5,19 +5,118 @@
 \section{BroadCast}
 後で書く
 \section{TreeVNCの設計方針}
-まず、多人数が参加している授業でVNCを使う場合に起こる問題は、最初で述べたように、一つのコンピュータに多人数が繋がり、処理性能が大幅に落ちてしまうところが問題である。
-この問題を解決する為に、クライアント同士を接続させ、画面描画のデータを受け取ったクライアントが次のクライアントにデータを流すという方法を考えた。
-画面共有を行いたいクライアントが一種のVNCサーバ自体にもなる。
+まず、多人数が参加している授業でVNCを使う場合に起こる問題は、最初で述べたように、一つのコンピュータに多人数が繋がり、
+処理性能が大幅に落ちてしまうところが問題である。
+
+この問題を解決する為に、クライアント同士を接続させ、画面描画のデータを受け取ったクライアントが次のクライアントに
+データを流すという方法で画面共有を行う方法を考えた。
+画面共有を行っているクライアントが一種のVNCサーバ自体にもなる。
+
 また、クライアント同士の接続はツリー構造で行うことで管理がしやすくなると考えた。
-クライアント同士の接続の管理はツリーの一番上にいるPC(Top)で行い、このTopだけがVNCサーバへ接続を行うようにする。
-今回作成したTreeVNCは、上記の実装でツリー状にクライアントを接続していくように実装を行った。
-画面の共有だけを行うように実装した。
+クライアント同士の接続の管理はツリーの一番上にいるPC(Top)で行い(図を入れたい)、このTopだけがVNCサーバへ接続を行うようにする。
+
+今回作成したTreeVNCは、上記の実装でツリー状にクライアントを接続していくように実装を行い画面の共有だけを行うように実装した。
+
+TreeVNCはTightVNCのjava版のビューアを元に作成を行った。実装の細かい内容は以下で説明する。TreeVNCはTightVNCのjava版のビューアを元に作成を行った。
+\newpage
 \section{木の生成}
+今回は、ホストに対しクライアントがツリー状に繋がっていくように実装した。ツリーの構成は以下の手順で行う。
+ \begin{enumerate}
+  \item クライアントが接続する際、ホストに接続をしているプロキシ(今後このプロキシのことをTopと記述する)に接続する。
+ \item Topはクライアントにどこに接続すれば良いかを知らせる。
+ \item クライアントはTopから指定されたノードに接続を行う。
+ \end{enumerate}
+\subsection{Topの仕事}
+Topはjava.util.LinkedListでクライアントの情報を保持している。
+
+TopはtreeBranch(木の分木数)を定数で持っていて
+クライアントが接続してくるごとにcounterをインクリメントしていき
+LinkedListの(counter - 1)/treeBranche番目に入っている親の情報を
+接続してきたクライアントに教えることで木を構成することができる。
+\newpage
+\section{木の再構成}
+後で書く
+\newpage
+\section{クライアントとの通信}
+TreeVNCは、受け取った画面の描画データをそのまま自分に繋がっている次のクライアントに送信する。
+描画データを受け取ったクライントはまた次のクライアントへデータをそのまま送信する。
+内部では、まず受け取った描画データの読み込みを先に行いBytebufferでコピーを行う。
+次にクライアントへの送信と自身のビューアへの描画を並列に行う。
+\subsection{FramebufferrUpdate}
+RFB プロトコルでの画面の描画の更新は、FramebufferUpdateで行われる。
+FramebufferUpdateを受け取ることで画面の再描画が行われる。
+FrameBufferUpdateでは、メッセージタイプと画面の矩形の数がまず送られ、
+次にx座標、y座標、横幅、縦幅、エンコードのタイプ、描画データが矩形の数だけ送られてくる。
+描画データはエンコードのタイプに従った方法で送られてくる。
+
+\subsection{MulticastQueue}
+画面が更新された際に更新をクライアントに伝えなければならない。ノードが多数ある場合、一人一人に更新を知らせるのではなく、同時に画面の更新を知らせたい。
+同時に更新を知らせるために、CountDownLatchを用いてMultiCastQueueを作成した。
+
+CountDownLatch一回CountDownされたときに待機しているスレッドを解放するように宣言する。更新情報が来るまでawaitを用いてスレッドを待機させる。更新情報が来たときCountDownを行う。すると、スレッドが開放されるので同時に更新情報を参照することができる。
+\newpage
 
-\section{木の再構成}
-\section{MulticastQueue}
-\section{TimeOut}
-\section{ZRLEE}
+\begin{figure}[tb]
+\begin{center}
+\includegraphics[scale = 0.5]{fig/multicastqueue.eps}
+\end{center}
+\caption{
+クライアントへは並列にデータを送信する。
+}
+\label{figure:splaying}
+\end{figure}
+
+\subsection{TimeOut}
+MultiCastQueueを使ってのデータの取得には問題が発生した。
+それは、接続してきたクライアントがデータを取得しない状況、例えばサスペンド状態になったときにTopのメモリの中にデータが残り続けるというものである。
+メモリに残り続けたデータはやがてメモリオーバーフローを引き起こしてしまうのである。その様子を図2.2に示す。
+
+\begin{figure}[!htbp]
+\begin{center}
+\includegraphics[scale = 0.5]{fig/TimeOut2.eps}
+\end{center}
+\caption{
+クライアントサスペンド時のTopのメモリの様子。
+データが残り続けメモリを圧迫してしまう。
+}
+\label{figure:splaying}
+\end{figure}
+
+そこで、ある一定の時間がたつと代わりにデータを取得してくれるTimeOut用のスレッドを作成した。
+TimeOutスレッドはサスペンドしているクライアントの代わりにデータを取得する。
+
+\begin{figure}[!htbp]
+\begin{center}
+\includegraphics[scale = 0.5]{fig/TimeOut3.eps}
+\end{center}
+\caption{TimeOutが代わりにデータを取得する}
+\label{figure:splaying}
+\end{figure}
+
+TimeOutスレッドがクライアントの代わりにデータを取得することで、MulticastQueueの中からデータが削除されTopのメモリを圧迫することがなくなった。
+
+\section{圧縮の問題}
+VNCで扱うRFB プロトコルには、使えるエンコーディングのタイプの1つとしてZRLE(Zlib Run-Length Encoding)がある。
+ZRLEはZlibで圧縮されたデータとそのデータのバイト数がヘッダーとして付けられ送られてくる。
+Zlibはフリーのデータ圧縮及び解凍を行うライブラリである。
+可逆圧縮アルゴリズムの圧縮と解凍が行えるjava.util.zip.deflaterとjava.util.zip.inflaterを実装している。
+
+\subsection{java.util.zip.deflaterの実装の問題}
+Zlib圧縮は辞書を持っていて、その辞書に登録されているデータを元に解凍が行われる。
+しかし、java.util.zip.deflaterは現在持っている辞書を書き出すこと(flush)ができないことが分かった。
+辞書を書きだすことができない為、Zlib圧縮されたデータを途中から受け取ってもデータが正しく解凍を行うことができない。
+%元々のZlibの規約にはこの辞書をflushする機能があったがJavaには実装されていなかった。
+
+\subsection{ZRLEE}
+そこで、TopがZRLEで受け取ったデータをunzipし、データをzipし直して最後にfinish()
+をいれることで初めからデータを読んでいなくても解凍を行えるようにした(毎回新しい辞書を使うようにした)。
+このエンコードはZRLEEエンコードと定義した。
+一度ZRLEEエンコードに変換してしまえば、そのデータをそのまま流すだけで良い。
+よって変換はTopが行う一回だけですむ。
+ただし、deflater,inflaterでは前回までの通信で得た辞書をクリアしないといけないため、
+Topとクライアント側では毎回新しく作る必要がある(クライアント側はinflaterだけ)。
+また、ZRLEEはクライアント側が対応していなければならないという問題がある。
+
 \section{UserInterface}
 \section{lionAuthenticate}