[[ノート>ノート/ノート]]~
訪問者 &counter();  最終更新 &lastmod();~

**Webアプリへの道のり [#y7364920]

***画面表示 [#dc1c07c1]
たとえば、[[これ:http://www.officedaytime.com/dcaslj/index.html]]をまねしようと思うと、画面をうまくレイアウトして
表示しなければならない。方法には、古くはTABLEタグを使う手があるが
読みにくい・書き直しにくい、という問題がある。もう1つの方法は、
スタイルシートでpositionなどを使う方法がある。表示環境によって崩れるという
問題があるが、工夫次第でかなり防げるということだ([[CSSによる崩れない段組:http://desperadoes.biz/style/dan/)。これを第1候補にしたい。~
問題があるが、工夫次第でかなり防げるということだ([[CSSによる崩れない段組:http://desperadoes.biz/style/dan/]])。これを第1候補にしたい。~
CSSの概論については、たとえば[[スタイルシートの基本:http://www.kanzaki.com/docs/html/htminfo17.html]]参照)。

フレームでなくて画面分割をしようとすると、スタイルシードでがんばることになる。
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
 <html lang="ja">
 <head>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=shift_jis">
 <style type="text/css">
 *{margin:0; padding:0;}
 body{background-color:#ddd;width:900px;}
 
 #my_header{width:100%;border-bottom:2px solid #fff;background-color:#ccb; height:50px;}
 #my_footer{width:100%;clear:both;background-color:#ccb;border-top:2px solid  #fff;text-align:center; padding:1em 0;}
 
 .contents p{margin:1em 0;}
 li {list-style:none;}
 h1{padding-left:20px;}
 textarea {font-size:80%;}
 table.tab1 {border-spacing:10px 4px;}
 td.td1 {border:1px #333 solid; text-align:right; width:50px;}
 table.tab2 {background-color:#bbb; font-size:80%; width:350px;}
 table.tab3 {background-color:#fff; font-size:80%; width:350px;}
 td.td3 {background-color: #ff0;}
 
 #my_left {background-color:#d6d6bb;}
 #my_rights {background-color:#ddd6bb;}
 #my_leftupper{padding:1em 0 2em 1em;border:0px solid #fff;border-bottom:1px solid #fff}
 #my_leftlower{padding:1em 0 2em 1em;border:0px solid #fff;}
 #my_rightupper{padding:1em;border-left:1px solid #fff;border-bottom:1px solid #fff}
 #my_rightlower{padding:1em;border-left:1px solid #fff;}
 </style>
 
 <TITLE>CASL Simulator</TITLE>
 <meta http-equiv="content-style-type" content="text/css">
 
 <style type="text/css">
 <!--
 
 #my_left{position:absolute; left :0; top: 52px; width:450px;}
 #my_right{margin-left:450px;}
 
 --></style>
 </head>
 
 <body>
 <div id="my_header"><h1>CASL Simulator</h1></div>
 
 <div id="my_left">
 
  <div id="my_leftupper">
   <FORM action="mytest.php" method="post">
   <P><TEXTAREA rows="20" cols="20" name="sourceprogram">プログラム 
   </TEXTAREA></P>
   <P><INPUT type="submit" name="assemble" value="assemble">
      <INPUT type="submit" name="step" value="step"></P>
   </FORM>
  </div>
  <div id="my_leftlower">
   <table class="tab1">
    <tr><td>PC</td><td class="td1">0008</td><td>IR</td><td class="td1">3423</td><td></td><td></td></tr>
    <tr><td>GR0</td><td class="td1">0008</td><td class="td1">0303</td><td class="td1">2145</td><td class="td1">4426</td><td></td></tr>
    <tr><td>GR4</td><td class="td1">9753</td><td class="td1">8642</td><td class="td1">1212</td><td class="td1">6666</td><td></td></tr>
    <tr><td>ZF</td><td class="td1">1</td><td>SF</td><td class="td1">1</td><td>OF</td><td class="td1">0</td></tr>
   </table>
   <p>Memory</p>
   <table class="tab1">
    <tr><td>0000</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0008</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0010</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0018</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0020</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0028</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0030</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
    <tr><td>0038</td><td class="td1">0008</td><td class="td1">3423</td><td class="td1">2222</td><td class="td1">4343</td></tr>
   </table>
  </div>
 </div>
 
 <div id="my_right">
  <div id="my_rightupper">
   <div class="contents">
    <table class="tab2">
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
    </table>
   </div>
 
 
  </div>
  <div id="my_rightlower">
 
   <div class="contents">
    <table class="tab3">
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td class="td3">text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
     <tr><td>text text text text text text</td></tr>
    </table>
   </div>
  </div>
 </div>
 
 <!--<div id="my_footer"><p>FOOTER</p></div> -->
 
 </body>
 </html>

&ref(WS000001.JPG);

***PHPの向う側に、標準入出力を持つC言語のプログラムを走らせる [#pa4ad12e]
今考えているCASLシミュレータ(OpenCASL Linux版)では、シミュレータ起動後に
キーボード(標準入力)からコマンドを与えて、ステップ実行させる。毎回レジスタが
戻される。またメモリ値はコマンドを与えて読み出す。

このためには、標準入出力を持つプログラムをPHPの向う側で走らせるテクが
必要になる。それは、[[proc_open:http://php.benscom.com/manual/ja/function.proc-open.php]]で実現できる。このマニュアルページに載っている例は
 <?php
 $descriptorspec = array(
    0 => array("pipe", "r"),  // stdin は、子プロセスが読み込むパイプです。
    1 => array("pipe", "w"),  // stdout は、子プロセスが書き込むパイプです。
    2 => array("file", "/tmp/error-output.txt", "a") // はファイルで、そこに書き込みます。
 );
 
 $cwd = '/tmp';
 $env = array('some_option' => 'aeiou');
 
 $process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
 
 if (is_resource($process)) {
     // $pipes はこの時点で次のような形を取っています。
     // 0 => 子プロセスの stdin に繋がれた書き込み可能なハンドル
     // 1 => 子プロセスの stdout に繋がれた読み込み可能なハンドル
     // すべてのエラー出力は /tmp/error-output.txt に書き込みされます。
 
     fwrite($pipes[0], '<?php print_r($_ENV); ?>');
     fclose($pipes[0]);
 
     echo stream_get_contents($pipes[1]);
     fclose($pipes[1]);
 
     // デッドロックを避けるため、proc_close を呼ぶ前に
     // すべてのパイプを閉じることが重要です。
     $return_value = proc_close($process);
 
     echo "command returned $return_value\n";
 }
 ?>
であるが、この中の
 fwrite($pipes[0], '<?php print_r($_ENV); ?>');
を他のもので置き換えるために、「//」でコメントアウトしたところ、うまくいかなかった。結局、
 /* fwrite($pipes[0], '<?php print_r($_ENV); ?>'); */
の形でうまくいった。厄介であった。

で、任意のCプログラムを実行する環境として、
 <?php
 $descriptorspec = array(
    0 => array("pipe", "r"),  // stdin は、子プロセスが読み込むパイプです。
    1 => array("pipe", "w"),  // stdout は、子プロセスが書き込むパイプです。
    2 => array("file", "/tmp/error-output.txt", "a") // はファイルで、そこに書き込みます。
 );
 
 $cwd = '/tmp';
 $env = array('some_option' => 'aeiou');
 
 /*$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);*/
 $process = proc_open('/home/foo/src/halloworld', $descriptorspec, $pipes, $cwd, $env);
 
 if (is_resource($process)) {
     /*fwrite($pipes[0], '<?php print_r($_ENV); ?>');*/
     fwrite($pipes[0], 'ABC');
     fclose($pipes[0]);
     print( "<p>Returned: <br>" . stream_get_contents($pipes[1]) . "</p>" );
     fclose($pipes[1]);
 
     // デッドロックを避けるため、proc_close を呼ぶ前に
     // すべてのパイプを閉じることが重要です。
     $return_value = proc_close($process);
 
     echo "command returned $return_value\n";
 }
 ?>
のようなものが動くことが分かった。裏に置いたCプログラム(/home/foo/src/halloworld)のソースは、
 #include<stdio.h>
 main() {
   char buf[80];
   fgets(buf, sizeof(buf), stdin);
   printf("Hallo. This is %s\n", buf);
 }
のようなものである。

***内部状態を持つバックエンドプログラムとWebページ [#xe85dda0]
さて、今考えている「シミュレータ」のCプログラムは、メモリやレジスタ値を内蔵しており、外部からの「ステップ実行」コマンドによって実行を進める。つまり、シミュレータは内部状態を持つ。

Webは状態を持たない(ステートレス)ことが前提である。原則としてCGIプログラムはSubmitボタンを押すごとに実行され、表示をして終了する。次の画面による実行へつながる内部状態は、保持できない。

であるから、シミュレータを(内部状態を持ったままで)動かすためには、工夫が必要になる。
-第1の方法として、状態を持つプログラムをバックエンドで実行させておき、たとえばネットワークインターフェースを介してコマンドを送る。一般に複数のユーザが1つのサーバーを使うことになってしまうので、セッションを区別する必要がある。つまり、サーバー内ではセッションごとに内部状態を保持する。Webからはセッションを識別子としてサーバーにアクセスし、入力を送り出力を取り出す。セッションごとに別のサーバーを起動することも可能だが、その場合は識別子としてサーバーのID(たとえばプロセスID)をもって区別することになる。~
~
フロントエンドにあたるPHPプログラムでは、セッションを保持し、そのセッションとバックエンドサーバーでのセッションとを同一にするか何らかの表で関連付けておく。
-第2の方法として、シミュレータから内部状態を取り除いてしまう。内部状態はWeb画面とのやり取りのたび毎に、たとえばhidden INPUTとして保持する。シミュレータの場合、内部状態はレジスタ(PC、PSW等を含む)値とメモリ内容であるから、これらを毎回画面とやり取りして保持する。シミュレータ自体は、内部状態と外部入力をインプットとしてステップ演算し、結果の内部状態と外部出力を画面側に返す。~
~
この方法の欠点は、hidden INPUTが複雑になること、画面ごとの転送量が多くなることが挙げられるが、シミュレータの場合はレジスタ値やメモリ内容はどうせ画面に表示するので、hiddenである必要が無くなる。

いずれにしても、バックエンドのシミュレータのプログラムはかなり書き直す必要があり、今回のCASLシミュレータ程度だとゼロから書き直すのとあまり変わらないかもしれない。たとえば第2の方法だと、シミュレータ(ステップ実行)をPHPで書き直してもよいかも知れない。

***いろいろ考えた結果 [#q368b506]
-今回は、かなりシミュレータを書き直すことになるので、それならJavaのシミュレータを見つけたほうが簡単だろう。アプレットではないにしても、ダウンロードして実行すれば、たいていのマシン環境で実行できる。

-ただ、他のバックエンドプログラム、たとえば生命科学系の処理やシミュレーションの場合、同じようなことがしたくなるかもしれない。そのとき、状態を持つか持たないか、持たせるか持たせないかの判断が必要になりそうだ。また、PHPからCプログラムの起動、Web画面の分割構成などの知識は有益だろう。

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS