===第1回 資料===
テーマ:計算機実習室にある多数のPCを使ったゲームまたはアートの制作
目的:Javaによるメディア操作やネットワークプログラムの基本を学ぶ。
サブテーマ1:ネットワーク接続されたPC間の通信方法(含むマルチキャスト)を学ぶ
サブテーマ2:カメラ画像の処理法を学ぶ
サブテーマ3:(必然的に)Javaのキーボード入力と描画処理を学ばざるを得ない
スケジュール:
(第1回10/24)
・PC間通信プログラムを紹介
・簡単なプログラムの作成
。あるPCから特定のPCにデータを送る。受信したPCはデータを画面に表示
。あるPCから複数のPCにデータを送る。受信したPCはデータを画面に表示
。上記2方式で、受信したPCは受信データに応じて異なる画像(赤丸等)を表示
(第2回10/31)
・上の技術を使ってマルチPCゲーム、またはマルチPCアートを作る。
(各自、作品の提案を、10/24日までに研究室WiKiのProjectに記入しておくこと)
(第3回11/7)
・カメラ画像処理法を紹介
・簡単なプログラムの作成
。カメラからの画像をモザイク表示する
。カメラからの画像から赤、緑、青、らしき所を検出し、赤、青、緑に変える。
(第4回11/14)
・第3回の技術を利用しもう少し高度なプログラムを作る。
(例えば:動いたものが有ったかを検出するとか、色紙の色を当てるとか、じゃんけんをするとか)
(各自、作品の提案を、11/7日までに研究室WiKiのProjectに記入しておくこと)
(第5回11/21、6回11/28)
・上で学んだ通信とカメラ処理の技術を使ったゲームまたはアートの制作
(マルチPC通信とカメラ画像を統合するのがベストだが、1方を高度化するのでもよい。特にカメラの場合は複数のPCがからむ応用の方が面白い)
(各自、作品の提案を、11/21日までに研究室WiKiのProjectに記入しておくこと)
(注1) 他の人の提案にコメントをあげよう。作品提案の変更は可能。
(注2) 実施場所は5階ラウンジの予定
(12月以降のスケジュールは未定)
**Network Programのための知識確認 2006/10/24 furuya
* ネット通信にはPCを特定する “IPアドレス” と “ポート番号”が必要
(本当はIPアドレスはPCの通信ボードのアドレス)
大学のIPアドレスは、202.16.210.xxx 。
研究室内で使うローカルなIPアドレスは、 192.168.0.xxx 。
* ネットワーク通信形態に TCP と UDP がある。
TCP: 送信と受信が確認を取りながら通信
UDP: 送信が受信を無視してデータを垂れ流す
* TCPの通信形態は、 クライアント-サーバ方式で通信
* UDPの通信形態には、1対1通信のユニキャスト、と1対多のマルチキャストがある。
* ソケット: Javaでの通信プログラムは、PC同士がソケットという通信口を通して行う。
(注意:Javaのソケットはバイナリデータ<バイト配列に入ったデータ>をやりとりする約束になっている。そのため、文字列<String 型>を送るにはバイト列への変換は必要になる)
* 今回の実験では、TCPのクライアント-サーバモデル、UDPのマルチキャストを使う。
クライアント-サーバモデル マルチキャスト
sender 今日の資料
* 今日の課題:クライアント-サーバの上図の下3方式作成、マルチキャストの確認
* できた人は、データを受信したPCがモニタ画面上に赤丸を描く。これには上で作成したプログラムを、http://test1.fry.is.sci.toho-u.ac.jp/lecture/A4.htmlのF6.javaに組み込めばよい。
* *クライアント―サーバプログラム
(1) サーバプログラム
//NetServer
import java.net.*;
import java.io.*;
import java.util.Date;
public class NetServer{
public static void main(String[] args){
String msg; //送信データ用バッファ
ServerSocket servsock;//servsockオブジェクトの宣言
Socket sock; //sockオブジェクトの宣言
OutputStream out; //outオブジェクトの宣言
Date time;
try{
//サーバソケット作成
servsock = new ServerSocket(Integer.parseInt(args[0]));
while(true){
sock = servsock.accept(); //クライアントの接続要求監視
out = sock.getOutputStream(); //出力ストリーム作成
time = new Date();
msg = time.toString() + "\n"; //yyyy-mm-dd の日付変換
for(int i=0;i<msg.length();i++){
out.write(msg.charAt(i)); //送信データ書き込み
}
sock.close(); //接続終了
}
}catch(IOException e){ //標準エラー出力処理
System.err.println("io trouble");
}
}
}
(2)クライアントプログラム
//NetClient
import java.net.*;
import java.io.*;
public class NetClient{
public static final int Len = 1024;//bufサイズ
public static void main(String[] args){
int k; //bufに読み込まれたバイトの合計数
byte[] buf= new byte[Len]; //byte配列の宣言,領域の確保
//受信データ用buf
InputStream in = null; //inputオブジェクトの宣言,初期化
Socket socket; //socketオブジェクトの宣言
try{
//ソケット作成
socket = new Socket(args[0],Integer.parseInt(args[1]));
//入力ストリーム作成
in = socket.getInputStream();
}catch(IOException e){ //標準エラー出力処理
System.err.println("io エラー");
}
while(true){
try{
k = in.read(buf); //読み込んでbyte配列bufに格納
if(k==-1){
in.close(); //接続終了
break;
}
System.out.write(buf,0,k);//受信データディスプレイ出力
}catch(IOException e){ //標準エラー出力処理
System.err.println("io エラー");
System.exit(1);
}
}
}
}
PCのIPアドレスを調べるには、コマンドプロンプトでipconfig 相手がネットにつながっているかを調べるにはコマンドプロンプトで、 ping <相手のIPアドレス>
**マルチキャストプログラム例
(1)センダー
/** multicastセンダー
* multicastSender.java
* 用法例 >java multicastSender 224.0.0.1
*/
import java.net.*;
class multicastSender{
static final int MULTI_PORT = 10000;//マルチキャスト接続用ポート番号
static final int BUFSIZE = 1024; //バッファサイズ
static String message="Hello, I am a Sender.";
public static void main(String[] args)
{
MulticastSocket sock = null; //マルチキャストソケット
InetAddress ipadr = null; //IPアドレス
byte TTL = (byte)1; //TTL
byte[] buf = new byte[BUFSIZE];//送信バッファ
int len; //buf長
int k; //バイト数
if(args.length != 1){
throw new IllegalArgumentException(
"usage: >java multicastServer <IP_Address>");
}
try
{
//IPアドレス設定
ipadr = InetAddress.getByName(args[0]);
buf = message.getBytes();
len = buf.length;
//データグラムパケット設定
DatagramPacket packet = new DatagramPacket(
buf,len,ipadr,MULTI_PORT);
sock = new MulticastSocket();
sock.setTimeToLive(TTL);
sock.joinGroup(ipadr);
sock.send(packet); //データ送信
sock.leaveGroup(ipadr);
sock.close();
while(true){
}
}catch(java.net.SocketException e){
System.err.println(e);
}catch(java.io.IOException e){
System.err.println(e);
}
}
}
(2)レシーバ側
/** multicastレシーバー
* multicastReceiver.java
* 用法例 >java multicastReceiver 224.0.0.1
*/
import java.net.*;
class multicastReceiver{
static final int MULTI_PORT = 10000;//マルチキャスト接続用ポート番号
static final int BUFSIZE = 1024; //バッファサイズ
public static void main(String[] args)
{
int len; //データ長
int i; //キーインバッファクリアインデックス
byte[] wbuf = new byte[BUFSIZE];//ワークバッファ
MulticastSocket sock = null; //マルチキャストソケット
InetAddress ipadr; //マルチキャストIPアドレス
if(args.length != 1){
throw new IllegalArgumentException(
"usage: >java multicastReceiver <IP_Address>");
}
try
{
//マルチキャストソケット設定
sock = new MulticastSocket(MULTI_PORT);
//IPアドレス設定
ipadr = InetAddress.getByName(args[0]);
sock.joinGroup(ipadr);
byte[] buf = new byte[BUFSIZE];//受信バッファ
//データグラムパケット
DatagramPacket packet = new DatagramPacket(buf,buf.length);
sock.receive(packet); //データ受信
String recvdata = new String(packet.getData());
recvdata = recvdata.trim();
System.out.println(recvdata);//画面出力
sock.leaveGroup(ipadr);
sock.close();
while (true) {}
}catch(java.io.IOException e){
System.err.println(e);
}
}
}
===第2回資料===
情報科学実験II 第2回 ネット通信制作プログラムのヒント
1回では、ゲームを完成するのは難しそうなので、今考えているゲームまたはアートの基本部分を作ってみましょう。
第2回目作品の用件は、(1)画面に絵を表示、(2)ネットワーク通信、(3)3,4台のPCを使用。
私の持っている作品イメージが伝わらないといけないので、皆さんの提案をヒントに、いくつか例を考えてみました。参考(程度)にご覧ください。
例1:1つの丸が3台のPC上を
次々に動く。自分はどれかのPCの
前にいて、丸が自分の所に来たら
ボタンを押す。うまく押せたら色が変わる。
解法1(クライアントサーバ方式):PC同士でクライアントサーバを構成して、データを送り、丸を表示する。
解法2(マルチキャスト方式):もう1台PCを用意し、そこからマルチキャストでPC番号を送る。3台のPCは、自分の番号が送られてきた時、丸を描く。
例2:宝探し。
プレーヤはR1〜R3のキーを押す。宝の
場所なら丸を出す。
解法:Sから1〜3の内の1つの数を
R1〜R3にマルチキャストする。自分のPC
番号を受け取ったRが宝の場所。
例3:右図の実線のPCのキーを押すと、
隣(右や左)のPC画面の色が変わる。
解法:右のように点線のPCを用意し、
キーが押されたことを点線PCに送り、
色変更も点線PCから指示すると簡単かも。
(注)上の例では“キーを押すと”という話にしていますが、F6.javaを使う場合、マウスでボタンをクリックするようにした方が簡単かも。
**画像表示プログラム(F6.java)との統合法
(基本的には自力で挑戦すること。どうしても分からない場合以下を参照)
import java.awt.*;
import java.awt.event.*;
import java .io.* ;
import java.net.* ;
public class F6 extends Frame implements ActionListener{
int pc= -1;
Point p;
//主処理
public static void main(String args[]){
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
OutputStream out ; // 出力ストリーム
byte[] buff = new byte[1024] ; // 配列の定義
int n ;
Frame f=new F6();
f.setTitle("ボタンクリックで文字列表示");
f.setSize(640,400);
f.setVisible(true);
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
System.out.println( "接続を受け付けました." ) ;
System.out.print ( "キーボードから文字を入力すると" ) ;
System.out.println( "クライアントへ送られます." ) ;
System.out.println( "\"q\"入力するとプログラムは終了" ) ;
out = sock.getOutputStream() ;
// ループを無限に繰り返す
while( true ) {
n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ;
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
//部品セット
F6(){
setLayout(new FlowLayout());
Button b0=new Button("000");
Button b1=new Button("111");
Button b2=new Button("222");
b0.addActionListener(this);
b1.addActionListener(this);
b2.addActionListener(this);
add(b0);
add(b1);
add(b2);
p= new Point();
addWindowListener(new WinAdapter());
}
//閉じる
class WinAdapter extends WindowAdapter{
public void windowClosing(WindowEvent we){System.exit(0);}
}
//描画
public void paint(Graphics g){
String s="hello this is a string";
if(pc==0){
g.drawString(s,100,150);
}
if(pc==1){
g.drawRect(50,50,30,30);
}
if(pc==2){
g.drawOval(p.x,p.y,10,10);
p.move();
}
}
//イベント
public void actionPerformed(ActionEvent ae){
if(ae.getActionCommand()=="000"){
pc=0;
repaint();
}
if(ae.getActionCommand()=="111"){
pc=1;
repaint();
}
if(ae.getActionCommand()=="222"){
pc=2;
repaint();
}
}
//repaint()で画面クリヤーしないようにするには以下を3行を生かす
// public void update(Graphics g){
// paint(g);
// }
}
class Point {
int x= 50;
int y= 50;
void move() {
x= x + (int)(Math.random()*10);
}
}
* *マルチキャストのプログラム例
// MSend.java
// マルチキャストパケット送信プログラムです.
// キーボード入力を,マルチキャストパケットへ送信します.
// 使い方 java MSend
//
import java.net.*;
public class MSend {
public static void main( String[] arg ) {
byte[] buffer = new byte[1024] ;
final byte TTL = 1 ;
final int PORT = 1002 ;
try{
InetAddress chatGrp =
InetAddress.getByName( "224.0.0.1" ) ;
MulticastSocket mSocket = new MulticastSocket( PORT ) ;
mSocket.joinGroup( chatGrp ) ;
while( true ) {
int n = System.in.read( buffer, 0, buffer.length ) ;
if( n > 0 ) {
DatagramPacket dp =
new DatagramPacket( buffer, n, chatGrp, PORT ) ;
mSocket.send( dp, TTL ) ;
} else break ;
}
} catch ( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// MRecv.java
// マルチキャストパケットの受信プログラムです.
// 受信データを画面に表示します.
// 使い方 java MRecv
import java.net.* ;
public class MRecv {
public static void main( String[] arg ) {
byte[] buffer = new byte[1024] ;
final int PORT = 1002 ;
try {
InetAddress chatGrp =
InetAddress.getByName( "224.0.0.1" ) ;
MulticastSocket mSocket = new MulticastSocket( PORT ) ;
mSocket.joinGroup( chatGrp ) ;
while( true ) {
DatagramPacket rPacket =
new DatagramPacket( buffer, buffer.length ) ;
mSocket.receive( rPacket ) ;
if( rPacket.getLength() > 0 ) {
System.out.write( buffer, 0, rPacket.getLength() ) ;
}
}
} catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
* * 前回の解等例
// Server1.java
// このプログラムはポート番号1001番で動作するサーバです.
// キーボード入力をクライアントに送る.
// 使い方 java Server1
import java .io.* ;
import java.net.* ;
public class Server1 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
OutputStream out ; // 出力ストリーム
byte[] buff = new byte[1024] ; // 配列の定義
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
out = sock.getOutputStream() ;
// ループを無限に繰り返す
while( true ) {
int n = System.in.read( buff ) ; // キーボード読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ;
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Client1.java
// ネットワーク上のサーバに接続し,データを受け取ります.
// そのデータを画面に表示します.(1台のPCで実行すること)
// 使用法 java Client1
import java.io.*;
import java.net.* ;
public class Client1 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
InputStream iStream = null; // データ読み取り用オブジェクト
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
// 入力のストリームを作る
iStream = sock.getInputStream() ;
}
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
System.err.println( "サーバーからの情報を待ちます." ) ;
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = iStream.read( buff ) ; // 読み込み
if( buff[0] == 'q' ) break ;
System.out.write( buff, 0, n ) ; // 画面へ表示
}
sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Server2.java
// このプログラムはポート番号1001番で動作するサーバ.
// クライアントから送られてくるデータを表示.
// 使い方 java Server2
import java .io.* ;
import java.net.* ;
public class Server2 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
byte[] buff = new byte[1024] ; // 配列の定義
InputStream iStream = null; // データ読み取り用オブジェクト
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
iStream = sock.getInputStream() ; // 入力のストリームを作る
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = iStream.read( buff ) ; // 読み込み
if( buff[0] == 'q' ) break ;
System.out.write( buff, 0, n ) ; // 画面へ表示
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Client2.java
// ネットワーク上のサーバに接続し,キーボード入力をサーバに送る.
// そのデータを画面に表示します.
// 例 java client2
import java.io.*;
import java.net.* ;
public class Client2 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
OutputStream out = null ; // 出力ストリーム
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
out = sock.getOutputStream() ; //出力ストリームを作る
}
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
System.err.println( "サーバーからの情報を待ちます." ) ;
// ループを無限に繰り返す
while( true ) {
int n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ; //サーバに送信
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Server3.java
// このプログラムはポート番号1001番で動作するサーバ.
// クライアントから送られてくるデータを表示し、そのデータをサーバに送り返す.
// 使い方 java Server3
import java .io.* ;
import java.net.* ;
public class Server3 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
byte[] buff = new byte[1024] ; // 配列の定義
InputStream iStream = null; // データ読み取り用オブジェクト
OutputStream out = null ; // 出力ストリーム
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
iStream = sock.getInputStream() ; // 入力のストリームを作る
out = sock.getOutputStream() ; //出力ストリームを作る
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = iStream.read( buff ) ; // 読み込み
out.write( buff, 0, n ) ; //クライアントに返送
if( buff[0] == 'q' ) break ;
System.out.write( buff, 0, n ) ; // 画面へ表示
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Client3.java
// ネットワーク上のサーバに接続し,キーボード入力をサーバに送り、サーバ
// から送り返されてくるデータを画面に表示する. (1台のPCで実行すること)
// 実行法 java Client3
import java.io.*;
import java.net.* ;
public class Client3 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
byte[] ibuff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
InputStream iStream = null; // データ読み取り用オブジェクト
OutputStream out = null ; // 出力ストリーム
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
iStream = sock.getInputStream() ; // 入力のストリームを作る
out = sock.getOutputStream() ; //出力ストリームを作る
}
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
// ループを無限に繰り返す
while( true ) {
int n = System.in.read( buff ) ;// キーボード読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ; //サーバに送信
int in = iStream.read( ibuff ) ; // 読み込み
System.out.write( ibuff, 0, in ) ; // 画面へ表示
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Server4.java
// このプログラムはポート番号1001番で動作するサーバ.
// キーボード入力をクライアント送る.クライアントから送り返されるデータを表示.
// 使い方 java Server4
import java .io.* ;
import java.net.* ;
public class Server4 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
byte[] buff = new byte[1024] ; // 配列の定義
byte[] ibuff = new byte[4096] ; // 配列の定義
InputStream iStream = null; // データ読み取り用オブジェクト
OutputStream out = null ; // 出力ストリーム
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
iStream = sock.getInputStream() ; // 入力のストリームを作る
out = sock.getOutputStream() ; //出力ストリームを作る
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ;
int in = iStream.read( ibuff ) ; // 読み込み
System.out.write( ibuff, 0, in ) ; // 画面へ表示
if( buff[0] == 'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
// Client4.java
// ネットワーク上のサーバに接続し,サーバから送られてくるデータを
// サーバに返送.(1台のPCで実行すること)
// 実行法 java Client4
import java.io.*;
import java.net.* ;
public class Client4 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
InputStream iStream = null; // データ読み取り用オブジェクト
OutputStream out = null ; // 出力ストリーム
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
iStream = sock.getInputStream() ; // 入力のストリームを作る
int n = iStream.read( buff ) ; // 読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out = sock.getOutputStream() ; //出力ストリームを作る
out.write( buff, 0, n ) ;
}
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
// ループを無限に繰り返す
while( true ) {
int n = iStream.read( buff ) ; // 読み込み
out.write( buff, 0, n ) ;
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
===第3回資料 カメラ画像の処理===
参照“JMFプログラミングガイド”P.59のFa.java
長ったらしいプログラムですが、カメラから1フレーム(1画面のことで、1秒間に30フレーム位カメラから入力される)入ってくるごとに、P.62のprocessというメソッドが実行される。
画像はメモリに次の様に格納されている(画像サイズが2×3pixelの場合)。
画面(右図の正方形は1ピクセル)
メモリ(inDataとoutData)
この図のR(赤),G(緑),B(青)は、8ビットのバイト:故に、画素数×3バイトのメモリ領域が必要。(もしかすると、右下が配列の先頭かも?)
RGB=0,0,0が黒、255,255,255が白、255,0,0が赤、かも。
バイト配列への数値の代入はa[i]=0xff;とか、a[j]=-1;これは255のこと、a[k]=(byte)5;なんて方法があるかも。
process(in, out)を見ると、下図の様に入力画像inを出力画像outにinDataという配列を経由して送っています。
送ってる、と言っても注意が必要です。それは、配列の代入です。Javaでは配列をオブジェクトとして扱います(そのため配列の生成がやっかいだったのを思い出して下さい)。
オブジェクトのコピーは、オブジェクト自体をコピーして新しいオブジェクトを作るのではなく、共通のオブジェクトを別の名で呼べるようにするだけです。C言語で言えばポインタのコピーに相当します。
それでプログラムを見ると、プログラムの構造は以下の図のようになっていることが分かります。
このinData[]に書き込んだ画像がモニタに表示されます。
課題1:出力画像を赤成分だけで表示しよう。
課題2:左右または上下または左右上下反転した画像を表示しよう。
課題3:1フレーム前の画像と比較し、変化の有ったところを赤く塗ろう。
課題3のヒント:過去の画像をしまっておく配列を用意し、それと現画像の比較を行う。
(配列の中身を本当にコピーするには、System.arraycopyを使うと便利です。参照:
http://www.javaroad.jp/java_array2.htmなど)
System.arraycopy()は5つの引数を持ち、それぞれ、順番にソース配列、ソース配列の要素の索引の開始位置、転送先配列、転送先配列内の開始位置、コピーされる要素の個数になります。
* 過去の画像をしまっておく配列 byte [] oldData = new byte[240*320*3];
は、processの外(すぐ上あたりでよい)に置くこと。
===第4回資料 カメラ映像処理===
No Ideaな方への作品案
案1:画面を上下2つに分割し、下半分は1フレ
ーム前(古い)画像を表示。
さらに、画面を4つに分割し、下ほど古い画像を
表示するようにする。
案2:画面を3つに分け、真ん中を(予め撮影し
て置いた)背景にする。
さらに、中央(背景)部を透過にする。
案3:ボールが上からゆっくり落ちてくるように
描画する。
さらに、手を出すと跳ね返るとよい。
(ボールじゃなくて雪が降ってくるような描画でも美しいかも)
前回の課題のヒント
動く物質を検出する方法(process付近のみ)
1フレーム前のデータをoldDataに保存し、新しいデータと比較。色の変化量をcに3原色の差の絶対値として取得。変化の大きいピクセルを赤くしている。
byte [] oldData = new byte[240*320*3];//過去保存用
public int process(Buffer in, Buffer out) {
int i,j,k,l=0,m,a,b,c=0,d=0;
byte [] inData = (byte[]) in.getData();
byte [] outData = new byte[240*320*3];
for(i=0; i<240; i++){
for(j=0; j<320; j++){
c = 0;
for(k=0; k<3; k++){
d = ( i * 320 * 3 ) + ( j * 3 );
a = inData[ d + k ];
b = oldData[ d + k ];
c += Math.abs( a - b );
}
if( c > 400 ){ //色変化が大きいピクセルを赤く
outData[ d + 0 ] = 0x00;
outData[ d + 1 ] = 0x00;
outData[ d + 2 ] = -1;
}
else{
outData[ d + 0 ] = inData[ d + 0 ] ;
outData[ d + 1 ] = inData[ d + 1 ] ;
outData[ d + 2 ] = inData[ d + 2 ] ;
}
}
}
// 映像に黒帯を入れる
// for(int i=8000; i<14000; i++) inData[i]= 0x00;
/* 重ね書き---@
byte[] outData= (byte[]) out.getData();
for(int i=30000; i<40000; i++) outData[i]= 0x00; */
out.setData(outData);
out.setFormat(in.getFormat());
out.setLength(in.getLength());
out.setOffset(in.getOffset());
System.arraycopy(inData,0,oldData,0,320*240*3);
return BUFFER_PROCESSED_OK;
}
===第5回資料 今までに出会った問題点===
1.カメラからの色認識が少し変だった問題
下のプログラムはFa.javaのprocess()部です。赤成分が大きかったら、真赤にしようというプログラムですが、どうもうまくいってないようです。どうすればよいのでしょうか?
byte [] oldData=new byte[240*320*3];
public int process(Buffer in, Buffer out) {
int i,j,k,l;
byte [] inData = (byte[]) in.getData();
byte [] outData=new byte[240*320*3];
i=0;
while(i<230400){
if(inData[i+2]>200)
outData[i+2]=255;
i+=3;
}
out.setData(outData);
System.arraycopy(outData,0,oldData,0,240*320*3);
out.setFormat(in.getFormat());
out.setLength(in.getLength());
out.setOffset(in.getOffset());
return BUFFER_PROCESSED_OK;
}
2.サーバに多数のクライアントが食いつく場合
この場合、サーバスレッドのacceptで
(1)クライアントからの接続要求を受付け、
(2)クライアントのソケットを取得し、
(3)サーバスレッドを作り
(4)クライアントとサーバ間で交信
という処理を行う。
=サーバ=
// McServer.java
// ネットワーク上のサーバに接続し,クライアントからのデータを表示
// そのデータを画面に表示します.
// 例 java McServer
import java.net.*;
import java.io.*;
class McServerThread extends Thread {
protected Socket sock;
public McServerThread(Socket s) {
sock = s;
}
public void run() {
byte[] buff = new byte[1024] ; // 配列の定義
try {
System.out.println("Connected");
InputStream iStream = sock.getInputStream() ; // 入力のストリームを作る
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = iStream.read( buff ) ; // 読み込み
if( buff[0] == 'q' ) break ;
System.out.write( buff, 0, n ) ; // 画面へ表示
}
sock.close();
System.out.println("Connection Closed");
} catch (IOException e) {
System.err.println(e);
}
}
}
public class McServer {
static int port = 10007;
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(port);
Socket clientsock = null;
System.out.println("Server Ready");
while(true) {
clientsock = server.accept();
McServerThread t = new McServerThread(clientsock);
t.start();
}
} catch (IOException e) {
System.err.println(e);
}
}
}
=クライアント=
// McClient.java
// ネットワーク上のサーバに接続し,キーボード入力をサーバに送る.
// そのデータを画面に表示します.
// 例 java McClient
import java.io.*;
import java.net.* ;
public class McClient {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
OutputStream out = null ; // 出力ストリーム
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 10007 ) ;
out = sock.getOutputStream() ; //出力ストリームを作る
System.err.println( "サーバへ送るデータを入力して" ) ;
// ループを無限に繰り返す
while( true ) {
int n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ; //サーバに送信
if( buff[0] == (byte)'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
クライアントをマルチスレッドにすることも考えられる。
この場合はIPとPORTの同じクライアントサーバソケットを各スレッド内で作っていけばいいかな(だんだん疲れてきた)
2.1つのプログラムにクライアントとサーバのソケットを付けなくてはならないケースもある。ここでは、1つのプログラムがサーバスレッドとクライアントスレッドを持つものを示す。
各プログラムはキーボード入力を相手に送り表示する。単なる送受信なら1つのソケットでもできるが、こうする必要があるケースもある。
=クライアントサーバ1=
// ServerC1Th.java
// このプログラムはポート番号1001番で動作するサーバ.
// キーボード入力をクライアント送る.クライアントから送り返されるデータを表示.
// 使い方 java ServerC1Th (最初にこちらC1を実行)
import java .io.* ;
import java.net.* ;
public class ServerC1Th {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
byte[] buff = new byte[1024] ; // 配列の定義
OutputStream out = null ; // 出力ストリーム
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
sock = servsock.accept() ; //接続受付
System.out.println( "クライアントから接続されました!" ) ;
out = sock.getOutputStream() ; //出力ストリームを作る
ThreadC1 tc1= new ThreadC1();
tc1.start();
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ;
if( buff[0] == 'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
class ThreadC1 extends Thread {
byte[] ibuff = new byte[4096] ; // 配列の定義
InputStream iStream = null; // データ読み取り用オブジェクト
Socket csock;
public void run(){ //一回しか出力しない
try{
System.out.println( "スレッド開始" ) ;
csock= new Socket( "127.0.0.1", 1002 ) ;
iStream = csock.getInputStream() ;// 入力ストリーム作る
int in = iStream.read( ibuff ) ; // 読み込み
System.out.write( ibuff, 0, in ) ; // 画面へ表示
}
catch( Exception e ){}
}
}
=クライアントサーバ2=
// ServerC2Th.java
// このプログラムはポート番号1002番で動作するサーバ.
// キーボード入力をクライアント送る.クライアントから送り返されるデータを表示.
// 使い方 java ServerC2Th (最初にC1を実行)
import java .io.* ;
import java.net.* ;
public class ServerC2Th {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
byte[] buff = new byte[1024] ; // 配列の定義
OutputStream out = null ; // 出力ストリーム
try{
ThreadC2 tc2= new ThreadC2();
tc2.start();
// サーバソケットの作成
servsock = new ServerSocket( 1002 ) ;
sock = servsock.accept() ; //接続受付
System.out.println( "クライアントから接続されました!" ) ;
out = sock.getOutputStream() ; //出力ストリームを作る
// データの終了まで,以下のループを繰り返します
while( true ) {
int n = System.in.read( buff ) ; // kb読み込み
System.out.write( buff, 0, n ) ; // 画面へ表示
out.write( buff, 0, n ) ;
if( buff[0] == 'q' ) break ;
}
sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
class ThreadC2 extends Thread {
byte[] ibuff = new byte[4096] ; // 配列の定義
InputStream iStream = null; // データ読み取り用オブジェクト
Socket csock;
public void run(){ //一回しか出力しない
try{
System.out.println( "スレッド開始" ) ;
csock= new Socket( "127.0.0.1", 1001 ) ;
iStream = csock.getInputStream() ; // 入力のストリームを作る
int in = iStream.read( ibuff ) ; // 読み込み
System.out.write( ibuff, 0, in ) ; // 画面へ表示
}
catch( Exception e ){ System.out.println( "スレッドエラー" ) ;}
}
}
==
4.ソケット間通信に(バイトでなく)Objactを使う
データをバイトで送ると、数値や文字列を送るのにバイトへの変換が必要なので面倒。そこで、JavaのObjectクラスを送るようにする方法を紹介します。イメージ的には、整数も文字列も共通のObjectという箱に入れて送る感じ。
/**(予備知識:JavaのObjectクラス)
Javaではオブジェクトの頂点にObjectクラスってのがあって、全てのオブジェクトはこの下に位置しています。ですから、整数intや文字列StringもObjectとして扱うことができます(Objectクラスで用意されているメソッドが利用可能という意味)。ここでは整数intと文字列StringをObjectに変身させる方法と、Objectから元の整数と文字列に戻す方法を示します。(整数と文字列は、少し扱いが違うので注意!何故違うかは自習)
(i) 整数intをObjectに変身させる方法:整数intのObject版はIntegerです。
(ii) 文字列StringをObjectとして使う方法:
(上の2例ではたまたま変数名に、abc, ABCと大文字、小文字を使っていますが、abc,xyzとか全然別の変数名でかまいません)
**/
さて、ソケットはバイトデータを送るものなので、Objectを送る場合には若干変更が必要です。
バイトで送る時は出力ストリームを作るのにsock.getOutputStream()としていましたが、
Objectを送るには
ObjectOutputStream os= new ObjectOutputStream(sock.getOutputStream());とします。入力ストリームの場合も同様で、sock.getInputStream()としていたものを、
ObjectInputStream is= new ObjectInputStream( sock.getInputStream()) ;とします。
それでは、整数と文字列をObjectにして送るクライアントサーバプログラムを示します。
(A) 整数intをIntegerにして送る場合
=サーバ=
// Serveros1.java
// このプログラムはポート番号1001番で動作するサーバです.
// キーボード入力をクライアントに送る.
// 使い方 java Serveros1
import java .io.* ;
import java.net.* ;
public class Serveros1 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
OutputStream out ; // 出力ストリーム
byte[] buff = new byte[1024] ; // 配列の定義
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
// out = sock.getOutputStream() ;
ObjectOutputStream os= new ObjectOutputStream(sock.getOutputStream());
// ループを無限に繰り返す
int n=0;
while( n<2 ) {
Object on= "Hello";
System.out.println( on ) ; // 画面へ表示
os.writeObject( on );
n++;
}
// sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
=クライアント=
// Clientos1.java
// ネットワーク上のサーバに接続し,データを受け取ります.
// そのデータを画面に表示します.(1台のPCで実行すること)
// 使用法 java Cliento1
import java.io.*;
import java.net.* ;
public class Clientos1 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
InputStream iStream = null; // データ読み取り用オブジェクト
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
}
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
System.err.println( "サーバーからの情報を待ちます." ) ;
// 入力のストリームを作る
ObjectInputStream is= new ObjectInputStream( sock.getInputStream()) ;
// データの終了まで,以下のループを繰り返します
while( true ) {
Object on= null; // 読み込みデータ
on= is.readObject();
String n= on.toString();
System.out.println( n ) ; // 画面へ表示
}
// sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
==
(B)文字列を送るプログラム
=サーバ=
// Serveros1.java
// このプログラムはポート番号1001番で動作するサーバです.
// キーボード入力をクライアントに送る.
// 使い方 java Serveros1
import java .io.* ;
import java.net.* ;
public class Serveros1 {
public static void main( String args[] ) {
ServerSocket servsock = null ; // サーバ用ソケット
Socket sock ; // ソケットの読み書き用オブジェクト
OutputStream out ; // 出力ストリーム
byte[] buff = new byte[1024] ; // 配列の定義
try{
// サーバソケットの作成
servsock = new ServerSocket( 1001 ) ;
System.out.println( "クライアントからの接続を待ちます!" ) ;
sock = servsock.accept() ; //接続受付
// out = sock.getOutputStream() ;
ObjectOutputStream os= new ObjectOutputStream(sock.getOutputStream());
// ループを無限に繰り返す
int n=0;
while( n<2 ) {
Object on= "Hello";
System.out.println( on ) ; // 画面へ表示
os.writeObject( on );
n++;
}
// sock.close() ;
}
catch( Exception e ) {
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
=クライアント=
// Clientos1.java
// ネットワーク上のサーバに接続し,データを受け取ります.
// そのデータを画面に表示します.(1台のPCで実行すること)
// 使用法 java Cliento1
import java.io.*;
import java.net.* ;
public class Clientos1 {
public static void main( String[] args ) {
byte[] buff = new byte[4096] ; // 配列の定義
Socket sock = null ; // サーバ接続用ソケット
InputStream iStream = null; // データ読み取り用オブジェクト
try{
System.out.println( "サーバへ接続します!" ) ;
// ソケットを作成します
sock= new Socket( "127.0.0.1", 1001 ) ;
catch(Exception e){
System.err.println( "ネットワークエラー!" ) ;
System.exit( 1 ) ;
}
try {
System.err.println( "サーバーからの情報を待ちます." ) ;
// 入力のストリームを作る
ObjectInputStream is= new ObjectInputStream( sock.getInputStream()) ;
// データの終了まで,以下のループを繰り返します
while( true ) {
Object on= null; // 読み込みデータ
on= is.readObject();
String n= on.toString();
System.out.println( n ) ; // 画面へ表示
}
// sock.close() ;
}
catch( Exception e ) {
System.err.println( "ネットワークのエラー!" ) ;
System.err.print( e ) ;
e.printStackTrace() ;
System.exit( 1 ) ;
}
}
}
==
===第6回資料 XML(第1回目に示した予定を変更)===
配布資料:C Magazine 2001 2、”XML入門”
予備知識:XMLをHTMLの進化形あるいは発展形と考えないように。
<なーんだ、XMLってこれだけか!>
XML自体は、すごい言語でも何でもなく、単なる“タグ”を用いたデータ表現法と考えること。
配布資料Fig.3がXML文書の例(但し、Fig.3の宣言部は“おまじない”、DTDは普通使わないので無視)で、本体はFig.3の“文書”と書かれた部分。Fig.3の“文書”を見れば分かる通り、<と>で挟まれた(各自が勝手に決める)タグと、<>と</>で囲まれたデータ部よりなる。見れば分かるとおり、これがXML文書の全て。
<XMLのすごいところ>
みんながXMLをWeb標準文書と認めて、これを使う“仕掛け”を作ってしまったところ。
代表的な2つの仕掛け
(1)仕掛け1:XML文書をブラウザに表示する方法を示すXSLというスタイルシートを利用できるようにした。
資料のList.4はList.3のXML文書を、Fig.7のように表示するスタイルシートです。勘のよい人ならこの3つを見ればどうなっているのか分かる(かも)。
(2)仕掛け2:XML文書を(データベースなどの)データとして、プログラムで処理する(一般には処理結果をブラウザで表示することが多い)ための関数集(API関数と呼ばれる)を用意し公開した。
要するに関数を使ってXML文書の一部を簡単に取り出したり処理することができるようになった。
下の図は、その様子を示している。具体例としては、資料のP.25~26です。これはList7のXMLデータを検索してFig.9のように表示するもので、ブラウザに表示するHTML文書(List8)の4行目や17行目から、JavaScriptプログラム(List9)を呼んでいる。このList9の中で沢山のXML操作関数を使っている。
(注1) プログラムからはXMLをDOMというオブジェクトと(に?)して処理している。
(注2) Javaスクリプト以外JavaとかC++でもDOMを扱える。
1)List8の17でList9を呼ぶ 2)List9の19でList7をList8のアイランドに読み込む 3)List9の36でList8の24(=List7)を検索
(補)List7,List8,Fig.9,List9の関係
第6回の課題:画像が2つ指定されているXMLファイルがある。各画像は次のように記述されている。
<img>
<src>test.jpg</src>
<alt>テスト</alt>
<width>100</width>
<height>100</height>
</img>
(1) この2つの画像を並べて表示するxslファイルを作成しよう。
(2) ファイル名を入力すると画像を出力するjavascriptを作成しよう。
Javaスクリプトの基本構造は、配布資料List9を理解しベースにすること。
=第7回資料 Ajax(Asynchronous JavaScript+HTML)入門 Web2.0のインフラ)=
今回の話は、Webサーバ上にある“日々変更されるデータ(ベース)”をネットのユーザに、“どうやって提供するか”って話。(HTMLは表示だけでデータを蓄えられないので、データはWebサーバ上にファイルとして置いてある)そこで、このWebサーバ上のファイルを操作する仕組みが必要となる。
(仕組み1)CGI—付録A
(仕組み2)PHP—付録A
(仕組み3)Ajax—この下
JavaScriptでXMLを操作する方法は
前回学んだ(かな? 課題2です)。
要するに右図のように、XMLデータを
DOMオブジェクトにしてしまい、
それをJavaScriptから操作する。
操作するには、P.28のTable2を使用。
さて、本題Web2.0作成ツール Ajax (Ajax= JavaScript + XML )
前回の課題2とAjaxとの違いは、XMLファイルがWebサーバ上にあるってこと。
JavaScriptはユーザブラウザ上で実行されるためサーバの負担が少ない。
サーバとユーザPCが同時並列(非同期=Asynchronous)に動く。
AjaxはJavaScriptからXMLを操作する関数を提供している。
何故、こんな形態(JavaScript+XML)にこだわるか(Web2.0のツールと呼ばれるか)。
(1) GoogleMapが地図データをXMLで提供しAjaxで操作可(HPに地図を張り込める)
(この場合WebサーバはGoogleのサーバということになる。)
(2) Yahooがネット検索データベースをXMLで提供しているので、HPから直接検索可
(3) YahooがAjax用の色々なHP作成ツールを提供している。
(4) RSS,mooライブラリ,Rico,Scriptaculous(各種エフェクト(フェードとか))が使える
前回の課題2(とよく似た課題)のサーバ使用バージョン
==figs.html==
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<title>Sample</title>
<script src="prototype.js" type="text/javascript"></script>
<script type="text/javascript">
function tryAjax(uri){
target = "disp";
new Ajax.Updater(target, uri, {method: "get"});
}
</script>
<style type="text/css">
#disp{
border: 1px solid #aaa;
width: 250px;
height: 250px;
padding: 5px;
}
</style>
</head>
<body>
<form>
<input type="button" id="button01" name="button01"
value="No.1" onClick="tryAjax('fig1.xml')">
<input type="button" id="button02" name="button02"
value="No.2" onClick="tryAjax('fig2.xml')">
</form>
<div id="disp"></div>
</body>
</html>
========
==fig1.xml==
<div>
<p>figure 1</p>
<img src="fig1.jpg" alt="蝶">
</div>
========
==fig2.xml==
<div>
<p> figure2 </p>
<img src="fig2.jpg" alt="テントウ虫">
</div>
========
上の他、fig1.jpgとfig2.jpgを用意(ANHTTPをデスクトップに拡げたらこれら全てデスクトップに置く)
さらにライブラリprototype.jsを用意(http://prototype.conio.net/のJust the .js, pleaseからダウンロードし、prototype.jsと名づける)
後は、http://localhost/higs.htmlとすればよい。
Ajaxはサポートソフトが膨大なので、使う人が自分で勉強しましょう。(ツールやライブラリが沢山あって強力だが、まだみんなバラバラに開発されている感じ。将来もっと整理されるはず)
***前回の課題の答え***
(課題1)渡邉さんの作
--XMLファイル--
<?xml version="1.0" encoding="Shift_JIS" ?>
<?xml-stylesheet type="text/xsl" href="1.xsl" ?>
<image>
<img>
<src>deai.gif</src>
<alt>DEAI</alt>
<width>39</width>
<height>25</height>
</img>
<img>
<src>ringo.gif</src>
<alt>DEAI</alt>
<width>22</width>
<height>24</height>
</img>
</image>
--XSLファイル—
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" xml:lang="ja">
<xsl:template match="/">
<HTML lang="ja">
<HEAD>
<title>image</title>
</HEAD>
<body>
<xsl:apply-templates select="//*" />
</body>
</HTML>
</xsl:template>
<xsl:template match="src">
<img>
<xsl:attribute name="src">
<xsl:value-of />
</xsl:attribute>
</img>
</xsl:template>
</xsl:stylesheet>
----------------------------------------------------------
(課題2)
==items.html==
<HTML> <HEAD>
<SCRIPT
LANGUAGE="JavaScript" SRC="finditem.js"></SCRIPT>
</HEAD>
<BODY>
Gazo Kensaku
<FORM ID="controls">
number:<INPUT TYPE="TEXT"
NAME="itemId" VALUE="1" SIZE="4">
<INPUT TYPE="BUTTON"
VALUE="push" ONCLICK="finditem(controls,xml)">
</FORM>
<img src="fig0.jpg"
name="ans">
<xml
id="xml"></xml>
</BODY>
</HTML>
==finditem.js==
function
finditem(form, xmldocument){
var fname= "items.xml",
output=
form.output,
itemId=
form.itemId.value;
var document= parse(fname,
xmldocument),
topLevel=
document.documentElement;
searchItem(topLevel, itemId);
}
function
parse(docname, xmldocument){
xmldocument.async= false;
xmldocument.load(docname);
return xmldocument;
}
function
searchItem(node, itemId){
var child, i, text="";
for(i=0; i<2; i++) {
child=
node.childNodes(i);
if(child.childNodes.item(0).text == itemId) {
document.ans.src= child.childNodes.item(1).text;
break;
}
}
}
==items.xml==
<?xml
version="1.0" encoding="Shift_JIS" ?>
<?xml-stylesheet
type="text/xsl" href="item02.xsl" ?>
<image>
<img>
<num>1</num>
<src>fig1.jpg</src>
</img>
<img>
<num>2</num>
<src>fig2.jpg</src>
</img>
</image>
======
付録A
*count.cgiの1行目はperlのありか
*CGIはperlでなくてもよい
PHPでは、下のようになる(参照:http://php.s3.to/counter/)
付録B Webサーバの準備
(第1回の時、サーバを立ち上げましたが、原理はあれと同じです。PCのIPは第1回と同じだし、ポートが80番ってだけ)
ANHTTPってWindows用簡単Webサーバがあるのでこれを使おう。
http://www.st.rim.or.jp/~nakata/
(Webサーバとしてはこの外、最も知名度の高いWebサーバはApache、Black Jumbo Dogってのも有ります。)
(ANTHHPの自己解凍形式をダウンロードし、デスクトップでUnzipするとデスクトップに展開されるので、5号館3階の実験では、この方がよいかも)
後は、デスクトップにhtmlファイルを作りIEで
http://localhost/〜.html
とするとHPが見える。
Perlの準備
ダウンロードしてインストール、Perl\binの場所をCGIの1行目に書く。
PHPを使いたい人
PHPをダウンロードしてインストール
*
ANHTTPがCGI使えるようになっているか確認
*
ANHTTPがSSI(カウンタのようにページアクセス時に動作)使用可か確認。また、htmlファイルはshtmlとした方がよいかも。