view presen/index.html @ 9:323ac5548b5d default tip

add some some .graffle files
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Sat, 10 Sep 2011 14:27:11 +0900
parents 9ecd6c8cfb68
children
line wrap: on
line source

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<style>
.center {
margin-left: auto;
margin-right: auto;
text-align: center;
}
.textcenter {
text-align: center;
}
.taninaritop {
   margin: auto;
   width: 95%;
   font-weight: bold;
}
</style>
<title>2011/9/6</title>
<!-- metadata -->
    <meta name="generator" content="S5" />
    <meta name="version" content="S5 1.1" />
    <meta name="presdate" content="20110910" />
    <meta name="author" content="Nobuyasu Oshiro" />
    <meta name="company" content="University of the Ryukyu" />
<!-- meta temporary -->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
<!-- configuration extensions -->
<meta name="tranSitions" content="true" />
<meta name="fadeDuration" content="500" />
<meta name="incrDuration" content="250" />
<!-- configuration autoplay extension -->
<meta name="autoMatic" content="false" />
<meta name="playLoop" content="true" />
<meta name="playDelay" content="10" />
<!-- configuration audio extension -->
<meta name="audioSupport" content="false" />
<meta name="audioVolume" content="100" />
<meta name="audioError" content="false" />
<!-- configuration audio debug -->
<meta name="audioDebug" content="false" />
<!-- style sheet links -->
<link rel="stylesheet" href="ui/default_utf/slides.css" type="text/css" media="projection" id="slideProj" />
<link rel="stylesheet" href="ui/default_utf/outline.css" type="text/css" media="screen" id="outlineStyle" />
<link rel="stylesheet" href="ui/default_utf/print.css" type="text/css" media="print" id="slidePrint" />
<link rel="stylesheet" href="ui/default_utf/opera.css" type="text/css" media="projection" id="operaFix" />
<!-- embedded styles -->
<style type="text/css" media="all">
.imgcon {width: 100%; margin: 0 auto; padding: 0; text-align: center;}
#anim {width: 33%; height: 320px; position: relative;}
#anim img {position: absolute; top: 0px; left: 0px;}
</style>
<!-- S5 JS -->
<script src="ui/default_utf/slides.js" type="text/javascript"></script>
</head>
<body>

<div class="layout">
<div id="controls"><!-- DO NOT EDIT --></div>
<div id="currentSlide"><!-- DO NOT EDIT --></div>
<div id="header"></div>
<div id="footer">
<h1>セミナー: 2011/ 9/ 10</h1>
<h2>並列信頼研</h2>
</div>
</div>

<div class="presentation">


      <div class="slide">
        <h1>Java による授業向け画面共有システムの設計と実装 </li>
        <h3></h3>
	<li>大城 信康  谷成 雄</li>
        <h4><a href="http://ie.u-ryukyu.ac.jp/" rel="external">琉球大学 並列信頼研究室</a></h4>
        <div class="handout"></div>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>本日の内容</h1>
	<li>proramming4の課題で作ったTreeVNCの設計と実装</li>
	<li>TreeVNCを作るにあたって学んだJavaでの並列プログラミングの仕方やVNCのプロトコル話</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
 	<h1>TreeVNCの目的と背景</h1>
	<li>大学の講義中、スクリーンに映されている画面は後ろの席程見えずらい。 </li>
	<li>その問題を手元のPCにも写せるようにすることで解決しようと考えた。</li>
	<li class="incremental">60人以上での画面共有を行うシステムを目標とする。</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
        <h1>VNCによる画面共有</h1>
	<li>画面を共有する方法 -> VNC</li>
	<li>VNC: Virtual Network Computing </br>ネットワークを介してコンピュータを遠隔操作するプログラム </li>
	<li>VNCのリモートPCの画面を写す機能を利用する。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
        <h1>VNCを用いての画面共有</h1>
	<li>まず、iMacで複数のPCからVNCをかけてみた。</li>
	<li class="incremental">-> 10台と繋ぐ前にVNCでの画面がカクカクに... </li>
	<li class="incremental">さらにCPU使用率も跳ね上がった。</li>
	<li class="incremental">原因について考えてみる。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>通常のVNCの問題点</h1>
	<table class="center">
	  <tr>
	    <td width=50% >
	      <p style="text-aline: center;" >
	      <img clas="scale" src="./pix/NormalVNC3.png" width="450">
	      </p>
	      </td>
	    <td width=50% style="text-align: left;">
	      <li><small>VNC Serverの負荷が重い。</small></li>
	      <li><small>Server側の通信網1本への通信負荷が高い。</small></li>
	  </td>
	</tr>
	</table>
	  <p class="incremental" style="text-align: center;" >実際に測ってみた</p>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>通常のVNCの問題点</h1>
	<p style="text-align: center;">
	  <li>
	  <samll>1台と48台でVNCをかけた時のスループットとサーバ側のCPU使用率</small>
	  </li>
	</p>
	<table class="center" class="incremental" border=1>
	  <tr>
	    <td></td>
	    <td>スループット(単位:Byte)</td>
	    <td>CPU使用率</td>
	  </tr>

	  <tr>
	    <td>1台</td>
	    <td>20M<small>(最大速度)</small></td>
	    <td>55%</td>
	  </tr>

	  <tr>
	    <td>48台</td>
	    <td>4M</td>
	    <td>100%</td>
	  </tr>
	</table>
	<li>VNCに使われるCPUの使用率が100%になり、スループットが5分の1まで下がっている。</li>

      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>通常のVNCの問題点</h1>
	<li>サーバへのCPU負荷が高い</li>
	<li>1本の通信網への負荷が高い</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>VNCの問題点の解決策</h1>
	<p style="text-align: center;">
	<small>クライアントを木構造で接続させるTreeVNC</samll><br>
	<img class="scale" src="./pix/TreeVNC0.png" width="500" heigth="500"><br>
	</p>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>TreeVNCの利点</h1>
	<table class="center" width=100% style="text-align: center;">
	  <tr>
	    <td><small>通常のVNC</small></td>
	    <td><small>TreeVNC</small></td>
	  </tr>
	  <tr>
	    <td>
		<img class="scale" src="./pix/NormalVNC3.png" width="300">
	      </td>
	    <td>
	      <img src="./pix/TreeVNC3.png" width="300">
	    </td>
	  </tr>
	    </p>
	</table>
	<li>クライアントが増えてもかかる負荷一定。</li>
	<li>通信網1本に対する負荷が減り、安定した通信ができる(有線)。</li>
	</div>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>TreeVNCの利点</h1>
	<table class="center" width=100% style="text-align: center;">
	  <tr>
	    <td><small>通常のVNC</small></td>
	    <td><small>TreeVNC</small></td>
	  </tr>
	  <tr>
	    <td>
		<img class="scale" src="./pix/NormalVNC3.png" width="300">
	      </td>
	    <td>
	      <img src="./pix/TreeVNC3.png" width="300">
	    </td>
	  </tr>
	    </p>
	</table>
	<table class="center" border=1 cellspacing="0" width=100%>
	  <tr>
	    <td></td>
	    <td>通常のVNC</td>
	    <td>TreeVNC</td>
	  </tr>
	  <tr>
	    <td>最大負荷</td>
	    <td> N*データ量 (クライアントの数に比例) </td>
	    <td> (M+1) * データ量</td>
	  </tr>
	</table>
	<p style="text-align: center;"><small>クライアントの数をN、木構造の子供の数をMとする</small> </p>
	</div>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>TreeVNCの設計</h1>
	<li>木構造での接続</li>
	<li>クライアントの管理を行うTop Proxyを置く。</li>
	<li>データは木の下へと流していくようにする。</li>
	<li>tightVNC ViewerのJava版(ver 1.3)を元にTreeVNCの実装を行う。</li>
	<p style="text-align: center;">
	  <img class="scale" src="./pix/TreeVNC0.png" width="500" heigth="500">
	    </p>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>今回の主な内容</h1>
	<ul>
	  <li>RFB Protocol</li>
	  <li>データ転送量</li>
	  <li>ZRLE Encodingの問題</li>
	  <li>データ転送に用いたMulticastQueueについての説明</li>
	  <li>木構造の再構築(谷成)</li>
	</ul>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>RFB protocol</h1>
	<li>Remote Frame Buffer Protocol : <br>GUI操作によるリモートアクセス用の通信プロトコル。VNCで用いられる。</li>
       <table class="scale" width=100% >
	 <tr>
	   <td width=50%>
	     <img class="scale" src="./pix/VNC-Sequence-.png"  height=80%>
	     </td>
	     <td width=50% align="left">
	       <small>
	       <li><font color=blue>1~5</font>まではinitial seaquenceとなる。</li>
	       <li><font color=orange>6</font>以降は繰り返し行われる処理。画面のデータが転送されてくる。</li>
	       </small>
	     </td>
	 </tr>
	 </table>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>画像の更新(FramebufferUpdate)</h1>
	<li>転送される画面(フレームバッファ)のデータは変更があった部分(差分)だけが矩形単位で送られる。</li>
	<table class="center" width=100%>
	  <tr>
	    <td>
	      <img src="./pix/hadesScreen1.png">
	      </td>
	    <td>
	      <img src="./pix/rightArrow.png">
	      </td>
	    <td>
	      <img src="./pix/hadesScreen2.png">
	      </td>
	    </tr>
	    </table>
	    <small>
	    <p style="text-align: center;"><font color=red>□ </font>で囲まれている矩形のデータだけが送られてくる。 </p>
	    </small>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>RFB Protocol</h1>
	<li>FramebufferUpdateRequest:</li>
	<li><small>画面に差分が発生したらサーバから教えて貰うためのリクエスト</small></li>
<small>
<table width=100% style="text-align: center;">
<td width=50%>
<table border=1 cellspacing="0">
  <tr>
    <td>バイト数</td>
   <td><pre>型   [値]</pre></td>
    <td>説明 </td>
  </tr>

  <tr>
    <td>1</td>
    <td><pre>U8         3</pre></td>
    <td>message-type </td>
  </tr>

  <tr>
    <td>1</td>
    <td><pre>U8<pre></td> 
    <td>incremental</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>x-position</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>y-position</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>width</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>height</td>
  </tr>

</table>
</td>
<td>
<img src="./pix/TreeVNC1.png" width=90%>
</td>
</table>
</small>
<li><small>このリクエストはTop Proxyだけが行う。</small> </li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>RFB Protocol</h1>
	<li>FramebufferUpdate:<small>画面の更新データ</small></li>
<table width="100%">
<td width=50%>
<small>
<table border=1 cellspacing="0" >
    <tr>
    <td>バイト数</td>
   <td><pre>型   [値]</pre></td>
    <td>説明 </td>
  </tr>

  <tr>
    <td>1</td>
    <td><pre>U8          0</pre></td>
    <td>message-type </td>
  </tr>

  <tr>
    <td>1</td>
    <td><pre>U8<pre></td> 
    <td>padding</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>number-of-rectangles</td>
  </tr>

</table>
   <li><small>以下number-of-rectanglesの数だけ矩形のデータが続く</small></li>

<table width=100%>
<td>
<table border=1 cellspacing="0" width=100%>
    <tr>
    <td>バイト数</td>
   <td><pre>型   </pre></td>
    <td>説明 </td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>x-position</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>y-position</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>width</td>
  </tr>

  <tr>
    <td>2</td>
    <td><pre>U16<pre></td> 
    <td>height</td>
  </tr>

  <tr>
    <td>4</td>
    <td><pre>U32<pre></td> 
    <td>encoding-type</td>
  </tr>

  <tr>
    <td>...</td>
    <td><pre>...<pre></td> 
    <td>PIXEL DATA</td>
  </tr>


</table>
</td>
<td>
</td>

</table>
</small>
</td>
<td width>
  <img src="./pix/TreeVNC2.png" width=90%>
</td>
</table>

	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>RFB Protocol</h1>
	<li style="text-align: center;"><small>例:FramebufferUpdate</small></li>
<table class="center" border=1 cellspacing="0" width=50%>
  <tr>
    <td>x-position</td>
    <td>336</td>
  </tr>

  <tr>
    <td>y-position</td>
    <td>388</td>
  </tr>

  <tr>
    <td>width</td>
    <td>724</td>
  </tr>

  <tr>
    <td>height</td>
    <td>449</td>
  </tr>

  <tr>
    <td>encoding-type</td>
    <td>16(ZRLE)</td>
  </tr>

  <tr>
    <td>ZRLE</td>
    <td>...</td>
  </tr>
</table>

	<table class="center">
	  <tr>
	    <td>
	      <img src="./pix/hadesScreen1.png">
	      </td>
	    <td>
	      <img src="./pix/rightArrow.png">
	      </td>
	    <td>
	      <img src="./pix/hadesScreen2.png">
	      </td>
	    </tr>
	    </table>

	  </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>データ転送量</h1>
	<p style="text-align: center;">
	  <small>矩形の大きさと描画に必要なデータ量(単位:Byte)</small>
	</p>
	  <table class="center"  border=1 cellspacing="0" width=80%>
	    <tr>
	      <td>矩形の大きさ \ エンコード</td>
	      <td>RAW</td>
	      <td>ZRLE</td>
	    </tr>

	    <tr>
	      <td>724 * 449</td>
	      <!--
	      <td>1300304</td> 
	      <td>796642</td> 
	      -->
	      <td>1.3M</td>
	      <td>0.8M</td>
	    </tr>

	    <tr>
	      <td>1920 * 64</td>
	      <!--
	      <td>491520</td>
	      <td>309602</td>
	      -->
	      <td>0.5M</td>
	      <td>0.15M</td>
	    </tr>

	    <tr>
	      <td>1920 * 1080</td>
	      <!--
	      <td>8294400</td>
	      <td>3472780</td>
	      -->
	      <td>8.2M</td>
	      <td>3.4M</td>
	    </tr>

	  </table>

	<p style="text-align: center;">
	  <img src="./pix/dataLength.png" width="450" heigth="325"> <br>
	    <small>RAW、ZRLE、ZRLEEエンコードのデータ量の比較</small>
	</p>
	</div>
      <!-- PAGE -->
<!--
      <div class="slide">
	<h1>データ転送量</h1>
	<li>クライアントが60台とした時、通常のVNCと、2分木構成にしたTreeVNCの通信網への負荷の理論値を考える。</li>
	<table class="center" border=1 cellspacing="0" width=80%>
	  <tr>
	    <td></td>
	    <td>通常のVNC</td>
	    <td>TreeVNC</td>
	  </tr>
	  <tr>
	    <td>最大負荷</td>
	    <td> N * データ量(クライアントの数に比例) </td>
	    <td> (M+1) * データ量</td>
	  </tr>
	</table>
	<p style="text-align: center;"><small>クライアントの数をN、木構造の子供の数をMとする</small> </p>
	<li>N = 60、 M = 2 、使用するエンコードはZRLEとする。</li>
	<li>724 * 449 の画面分のデータ(0.8M)を送信するとする。 </li>
	
	</div>
-->
	<!-- PAGE -->
	<div class="slide">
	  <h1>データ転送量</h1>
	<p style="text-align: center;"> <small>理論値</small>
	<table class="center" border=1 cellspacing="0" width=80%>
	  <tr>
	    <td></td>
	    <td>通常のVNC</td>
	    <td>TreeVNC</td>
	  </tr>
	  <tr>
	    <td>最大負荷</td>
	    <td>48M</td>
	    <td>2.4M</td>
	  </tr>
	</table>
	<table class="center" width=100% style="text-align: center;">
	  <tr>
	    <td><small>通常のVNC</small></td>
	    <td><small>TreeVNC</small></td>
	  </tr>
	  <tr>
	    <td width=50%>
		<img class="scale" src="./pix/NormalVNC4.png">
	      </td>
	    <td>
	      <img src="./pix/TreeVNC5.png">
	    </td>
	  </tr>
	    </p>
	  </table>
	  <small>	  
	  <p style="text-align: center">クライアント:60台 TreeVNCは2分木でTreeを構成 </p>
	  </small>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>エンコード</h1>
	<li>MacintoshでZRLEを使ってVNCを行うことができる</li>
	<li>データ量がRAWデータの約4分の1ですむ。</li>
	<li class="incremental">TreeVNCではこのZRLEを扱っている。</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLE</h1>
	<li>ZRLE : Zlib Run-Length Encoding </li>
	<ul>
	  <li>Zlib圧縮(gzip)されたデータ扱うエンコーディング。</li>
	</ul>
	  <li>最初の4バイトにはZlibのデータの長さが、続いてZlibのデータが送られてくる。</li>
	  <small>
	  <table border=1 width=50% cellspacing="0">
	    <tr>	
      <td>バイト数</td>
	      <td><pre>型 </pre></td>
	      <td>説明 </td>
	    </tr>
	    <tr>
	      <td>4</td>
	      <td>U32</td>
	      <td>length</td>
	    </tr>
	    <tr>
	      <td>length</td>
	      <td>U8 array</td>
	      <td>ZlibData</td>
	    </tr>
	  </table>
	  </small>
	  <li>VNCでZRLEを使う場合は単一のZrleInStreamを使ってデータの解凍を行う。</li>
	  <li class="incremental">問題が発生</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLEの問題</h1>
	<li>Zlibデータは辞書を元にデータの解凍を行う</li>
	<li class="incremental">辞書がなければデータを正しく解凍できない</li>
      </div>
      <div class="slide">
	<h1>ZRLEの問題</h1>
	<li>辞書はZlibデータの最初に送られてくる。</li>
	<li>もしも、ZRLEのデータを最初から送っているのなら、辞書も送ることができる。</li>
	<li>データの途中から送ると辞書は送られず、正しく解凍を行うことができない。</li>
	<table class="textcenter" width=100%>
	  <tr>
	    <td>
	  <img src="./pix/ZRLE.png" width="600" >
	  </td>
	<td>
	    <img src="./pix/ZRLE2.png" width="600" >
	  </td>
	</tr>
	  </table>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLEE</h1>
	<li>そこで、ProxyがZRLEを使ってデータを受け取り圧縮し直して木の下へ流していくことにした。</li>
<small>	
	<pre>
Deflater nDeflater = deflater; // new Deflater();
LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>();
unzip(inflater, inputs, 0 , out, INFLATE_BUFSIZE);
// dump32(inputs);
int len2 = zip(nDeflater, out, 0, bufs);
</pre>
</small>
<li><small>この圧縮し直したデータはZRLEEと名付けた。</small></li>
	<table class="textcenter" width=100%>
	  <tr>
	    <td>
	      <img src="./pix/ZRLEE2.png" width="600">
		</td>
	      <td>
	      <img src="./pix/ZRLEE3.png" width="600">
		</td>
	      </tr>
	    </table>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLEE</h1>
	  <li>クライアント側は毎回新しいZRLEのストリームを使うようにする。</li>
	  <pre>
	    if (rfb.updateRectEncoding==RfbProto.EncodingZRLEE) 
   	       zrleInStream = null;
	    if (zrleInStream == null)
	       zrleInStream = new ZlibInStream();
	  </pre>
	  <li>Zlibの規約には辞書の取り出し(flush)については書かれている。</li>
	  <li>Javaでは実装されていなかった為、このような方法をとることになった。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLEEの疑問点</h1>
	<li>ZRLEEには毎回辞書が付与されている。</li>
	<p class="textcenter">
	  <img src="./pix/ZRLEE2.png" width="600">
	</p>
	  <li class="incremental">ZRLEに比べるとデータ量は増えないのか...?</li>
	  <li class="incremental">-> ZRLEと比較してみるとデータ量は少なくなった。</li>
      </div>
      <!-- PAGE -->
	<div class="slide">
	  <h1>ZRLEEのデータ量</h1>
	  <p style="text-align: center;">
	    <small>1920*1080の描画にかかったデータ量</small>
	  </p>
	<table class="textcenter"  width=100%>
	  <tr>
	    <td width=50%>
	      <img src="./pix/dataLength.png" width="450" heigth="325">
	    </td>
	    <td>
	     <table border=1 cellspacing="0" width=100%>
	       <tr>
		 <td></td>
		 <td>ZRLE</td>
		 <td>ZRLEE</td>
	       </tr>
	       <tr>
		 <td>データ量</td>
		 <td>3.4M</td>
		 <td>3.2M</td>
	       </tr>
	     </table>
	    </td>
	  </tr>
	  </table>
	  <li>ZRLEよりデータ量が多くなるどころか少ない。</li>
	  <li>原因</li>
	  <ul>
	    <li>ZRLEEは送られるデータ毎で最適な辞書が使われる。</li>
	  </ul>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>ZRLEEを使う利点</h1>
	<li>データ量が少なくですむ</li>
	<ul>
	  <li>ZRLEよりも少なくですむ可能性がある。</li>
	  <li>圧縮率が高い為プロキシのメモリを食わないですむ。</li>
	</ul>
	<li>一度ZRLEEに圧縮してしまえば、データはそのまま流すことができる。</li>
	<li>TreeVNCの設計にある「データを木の下へ流す」の条件を満たす。</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>データの転送</h1>
	<li>クライアントから接続されるとsenderスレッドが作られる。</li>
	<li>senderスレッドによりデータの転送は並列に行われる。</li>
 	<p class="textcenter">
	  <img  src="./pix/MulticastQueue3.png">
	  </p>
	<li class="incremental">MulticastQueueクラスを用いた並列な転送を行った。</li>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>MulticastQueue</h1>
	<li>MulticastQueue:データを順序よく読み込ませるクラス</li>
	  <table class="textcenter" border=1 cellspacing="0" width=100%>
	    <tr>
	      <td width=50%>
		<img src="./pix/MulticastQueue2.png">
		</td>
	      <td>
		<img src="./pix/MulticastQueue.png">
	      </td>
	      </tr>

	      <tr>
		<td>
		  次のデータがなければwaitする
		</td>
		<td>
		  データがputされ次第読み込みを再開する
		</td>
	      </tr>
	    </table>
	      <p><small>
		  MulticastQueueは、java.util.CountDownnLatchにより実装されている。
	      </small></p>
	</div>
      <!-- PAGE -->
<!--
      <div class="slide">
	<h1>MulticastQueue</h1>
	<li>MulticastQueueからデータを取り出し子供に送っている部分のソース</li>
	<pre>
LinkedList<ByteBuffer> bufs = c.poll();
int inputIndex = 0;
ByteBuffer header = bufs.get(inputIndex);
if (header==null) continue;
writeToClient(os, bufs, inputIndex);
</pre>
<li>c.poll(inputIndex) 内部では次の処理を行っている。</li>
<pre>
latch.await();
return next;
</pre>
<li>次のデータが用意できるまでawait()で待つのである。</li>
	</div>
-->
      <!-- PAGE -->
<!--
      <div class="slide">
	<h1>MulticastQueue</h1>
	<li>データは作られるとMulticastQueueにputされる。</li>
	<p><small>put内部ではつぎの処理が行われる。</small></p>
	<pre>
Node<T> next = new Node<T>(item);
tail.set(next);
tail = next;
	  </pre>

<small>
<p>
set()内部ではlatchがcountDown()され、await()で止まっていたスレッドが動き出す。
</small>
      </div>
-->
      <!-- PAGE -->
      <div class="slide">
	<h1>MulticastQueue</h1>
	<table class="textcenter" style="margin-top: 50px" width=100% border=1 cellspacing="0">
	  <tr>
	    <td>
	  <img src="./pix/MulticastQueue_proxy2.png" width="600">
	    </td>
	  <td  style="text-align: left;" width=50%>
	    <li>putでデータの入力</li>
	    <li>pollでデータの取り出し</li>
	    <li>Proxyは常に最新のデータの参照を渡す</li>
	    </td>
	  </tr>
	    <tr>
	      <td width=50%>
		<img src="./pix/MulticastQueue_proxy3.png" width="600">		
	      </td>
	      <td style="text-align: left;">
		<li>クライアントは最新のデータから読み込み始める。</li>
	      </td>
	    </tr>
	</table>
	      <p class="textcenter">実際のソースでみてみる</p>
      </div>
      <!-- PAGE -->
      <div class="slide">
	<h1>MulticastQueueの問題点</h1>
	<li>クライアントがデータを読み込まない時...
	<table class="textcenter" width=100% style="margin-top: 50px; margin-bottom: 50px;">
	  <tr>
	    <td width=50%>
	      <img src="./pix/MCTimeOut1.png">
	    </td>
	    <td>
	      <img src="./pix/MCTimeOut2.png">
	    </td>
	  </tr>
	</table>
	    <li>読み込まれないデータはProxyのメモリに残り続ける。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>MulticastQueueの問題点</h1>
	<li>TimeOut(TO)スレッドを走らせ、最新のデータから取得できるようする。</li>
	<table class="textcenter" width=100% style="margin-top: 50px;  margin-bottom: 50px;">
	  <tr>
	    <td width=50%>
	      <img src="./pix/MCTimeOut3.png">
	    </td>
	    <td>
	      <img src="./pix/MCTimeOut4.png">
	    </td>
	  </tr>
	</table>
	  <li>どこからも参照されないデータはProxyのメモリから削除される。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>並列なデータ転送に関して...</h1>
	<li>次のソースを見てください。</li>
	<pre>
executor = Executors.newSingleThreadExecutor();
...
...
executor.execute(new SendThread(out, buffer));
	</pre>
	<li class="incremental">スレッド間の同期ができていない。</li>
	<li class="incremental">実はこのソース、僕が最初に書いた並列にデータを転送させる部分です。</li>
	<li class="incremental">一回のデータ転送に1スレッドを立てているというとても酷いソース</li>
	<li class="incremental">3台つなげただけでプログラムが落ちた。</li>
	<li class="incremental">こんなプログラムだけは書かないようにしましょう...</li>
	</div>
      <!-- PAGE -->

<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml1.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     requestHostName();
   </Font>
     <br>
     プロキシに対してホストのアドレスを要求する関数。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml2.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     transferParentAddress();
     </Font>
     <br>
       クライアントに接続先を教える関数。
       <br>
       <br>
       実際にクライアントにおくっているデータは
       <br>
         parentAddress -> 親のアドレス
       <br>
         parentNum     -> 親の番号
       <br>
       treeNum         -> 自分の木の番号
       <br>
       leaderFlag      -> リーダフラグ
       <br>
         の4つである。
       <br>
         リーダーは子供の中で一番若い番号の人がなる。
       <br>
         リーダーフラグは木の再構成の際に使用する。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml3.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     connectAndAuthenticate();
     </Font>
     <br>
       プロキシから受け取ったデータをもとに接続を開始する関数。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml4.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
     新しいクライアントが来るたびに今まで説明した3つの関数を呼び出す。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml5.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml6.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml7.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml8.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/uml9.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
     ここで接続先がクライアント1になっているがこれはプロキシ側で
     <br>
     <Font color="red">
     親の番号 = (自分の番号 - 1) / 親に対する子どもの数
     </Font>
     <br>
     を計算してどの親に接続させれば良いかを決めてクライアントに報告している。
     <br>
       このように番号で木を管理している。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml1.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
     クライアント1が落ちた時の再接続の処理についての説明。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml2.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     lostHost();
     </Font>
     <br>
       木を構成する際にリーダを決めたが、そのリーダだけが呼び出す関数。
     <br>
       プロキシに対し落ちた親(クライアント1)の情報を報告する。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml3.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     reportLastNode();
     </Font>
     <br>
     ラストノードに対し落ちたクライアントの代わりをするように命令を出す。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml4.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     connectAndAuthenticate();
     </Font>
     <br>
      プロキシから受け取ったデータをもとに接続を開始する関数。
     <br>
       この時クライアント6がクライアント1に変わる。

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml5.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     transferParentAddress();
     </Font>
     <br>
       落ちた親の子供たちに対し新しい親のアドレスを報告する関数。
   </Font>
     </td>
     </td>
   </table>
 </div>
</div>


<div class="slide">
 <div class="taninaritop">
   <h1>木の再構成手順</h1>
   <table class="tanitable">
     <td>
     <td>
   <center><img class="scale" src="pix/reuml6.png" alt=""></center>
     </td>
     </td>
     <td>
     <td>
   <Font size="6">
   <Font color="red">
     connectAndAuthenticate();
     </Font>
     <br>
      プロキシから受け取ったデータをもとに接続を開始する関数。

   </Font>
     </td>
     </td>
   </table>
 </div>
</div>

<!-- PAGE -->
<div class="slide">
 <div class="taninaritop" >
   <h1>木の再構成手順</h1>
   <center><h2>再構成後の木</h2></center>
   <center><img class="scale" src="pix/reuml7.png" alt=""></center>
 </div>
</div>

<!-- PAGE -->

      <div class="slide">
	<h1>最後に</h1>
	<li>今回のTreeVNCは大学の授業「programming4」で作り始めた。</li>
	<li>Javaは基本知識だけ、VNCの仕組みについては全く知らない状態からのスタートあった。</li>
	<li>木の再構成、MulticastやZRLEの問題にも出会ったがなんとかクリアすることができた。</li>
	<li class="incremental">Javaでの分散プログラミングは考えていたよりも楽であった。</li>
	</div>
      <!-- PAGE -->
      <div class="slide">
	<h1>質問タイム</h1>
	</div>
      <!-- PAGE -->
<!--
      <div class="slide">
	<h1>テスト環境:</h1>
	<li>CUI版のVNCクライアントを作成</li>
	<li>48台あるクラスタでCUI版のクライアントをはしらせてVNCをかけさせる。</li>
	<li>最初の1台目と48台めをGUI版のクライアントで接続を行い見比べてみる。 </li>
	</div>
-->
      <!-- PAGE -->
<!--
      <div class="slide">
	<h1>既存のプログラムとの比較</h1>
	<li>VNC Reflector</li>
	<ul>
	  <li>tightVNCの作者が作成したプログラム</li>
	  <li>VNC Reflecotrにクライアントが接続することでVNCを行うことができる</li>
	</ul>
	</div>
-->
      <!-- PAGE -->
</div>
</body>
</html>