クラサバとエージェント
戻る
::::::::::::::
result.txt
::::::::::::::
$ ./Agent.sh
-- listing properties --
portNumber=80
messageEncoding=Shift_JIS
Server started...
-- listing properties --
defaultConnectTimeout=3000
defaultReadTimeout=5000
serverPortNumber=80
serverHostName=192.168.0.2
messageEncoding=Shift_JIS
Agent started...
装置名=読取装置A (deviceId=001): イベントを取得しています!
/*** DEBUG ***/ connecting... hostName=192.168.0.2 portNumber=80
java.nio.channels.SocketChannel[connected local=/192.168.0.2:80 remote=/192.168.0.2:1231] connect.
時刻: Sun Jul 10 23:24:05 JST 2005
[クライアントからの要求電文]
DEVICEID: 1
OPERATOR: 岸 康弘
PROCEDURE: 登録
TIMESTAMP: 2005-07-10 23:24:05
この要求の受付番号=1
サーバ側からの応答: 受け取りました! 受付番号=1
装置名=読取装置B (deviceId=002): イベントを取得しています!
/*** DEBUG ***/ connecting... hostName=192.168.0.2 portNumber=80
java.nio.channels.SocketChannel[connected local=/192.168.0.2:80 remote=/192.168.0.2:1232] connect.
時刻: Sun Jul 10 23:24:05 JST 2005
[クライアントからの要求電文]
DEVICEID: 2
OPERATOR: 山田 太郎
PROCEDURE: 検査
TIMESTAMP: 2005-07-10 23:24:05
この要求の受付番号=2
サーバ側からの応答: 受け取りました! 受付番号=2
::::::::::::::
Agent.sh
::::::::::::::
#!/bin/sh
PKGNAME=AgentBasedTracker
CLASSPATH=.\;../../lib/${PKGNAME}.jar
java -cp ${CLASSPATH} ${PKGNAME}.Server &
sleep 1
java -cp ${CLASSPATH} ${PKGNAME}.Agent
::::::::::::::
AbstractProcedure.java
::::::::::::::
package AgentBasedTracker;
import java.util.*;
import java.io.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class AbstractProcedure {
protected String name;
protected AbstractProcedure( String name ) {
this.name = name;
}
protected String getName() {
return name;
}
}
::::::::::::::
Agent.java
::::::::::::::
package AgentBasedTracker;
import java.util.*;
import java.io.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class Agent implements Runnable {
/** 監視対象のデバイス */
private List deviceList;
/** サーバのホスト名 */
private String hostName;
/** サーバのポート番号 */
private int portNumber;
/** サーバとやりとりするメッセージのエンコーディング */
private String encoding;
/** プロパティファイルのPATH */
private String propFileName = "./agent-config.xml";
public void addDevice( Device device ) {
if ( deviceList == null ) {
deviceList = new LinkedList();
}
// デバイスをエージェントの関係性を作成
deviceList.add( device );
device.setAgent( this );
}
public void getProperties() {
// プロパティをロードする
Properties prop = new Properties();
try {
InputStream stream = new FileInputStream( propFileName );
prop.loadFromXML( stream );
stream.close();
// 一覧を出力
prop.list( System.out );
//=========================================================
// 各プロパティを取得
//=========================================================
hostName = prop.getProperty( "serverHostName" );
portNumber = new Integer( prop.getProperty( "serverPortNumber" ) ).intValue();
encoding = prop.getProperty( "messageEncoding" );
/******************************************************************************/
/* 接続タイムアウトの設定; 設定された時間でコネクトできない場合はタイムアウト */
/******************************************************************************/
System.setProperty ( "sun.net.client.defaultConnectTimeout",
( String ) prop.getProperty( "defaultConnectTimeout" ) );
/**********************************************************************************/
/* 読み取りタイムアウトの設定; 設定された時間で読み取りできない場合はタイムアウト */
/**********************************************************************************/
System.setProperty ( "sun.net.client.defaultReadTimeout",
( String ) prop.getProperty( "defaultReadTimeout" ) );
} catch ( IOException e ) {
e.printStackTrace();
}
}
public void start() {
( new Thread( this ) ).start();
}
public void run() {
System.out.println();
System.out.println( "Agent started..." );
System.out.println();
while ( true ) {
// イベントの発生をチェックする
checkEvents();
try {
Thread.sleep( 500 );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
/**
* 登録されたデバイスからイベントの発生を確認する
*/
private void checkEvents() {
Iterator iterator = deviceList.iterator();
while ( iterator.hasNext() ) {
Device device = ( Device ) iterator.next();
if ( device.hasEvent() ) {
System.out.printf( "装置名=%s (deviceId=%03d): イベントを取得しています!\n",
device.getName() , device.getId() );
Event event = obtainEvent( device );
Operator operator = event.getOperator();
Procedure procedure = event.getProcedure();
try {
Calendar date = Calendar.getInstance();
// サーバにメッセージを送信
communicate( "DEVICEID: " + device.getId()
+ "\n"
+ "OPERATOR: " + operator.getName()
+ "\n"
+ "PROCEDURE: " + procedure.getName()
+ "\n"
+ "TIMESTAMP: " + GenericUtils.getYYYYMMDD( date ) + " " + GenericUtils.getHHMISS( date )
+ "\n" );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
}
/**
* デバイスから生成されたイベントを取得する
* @param device デバイス
*/
private synchronized Event obtainEvent( Device device ) {
Event source = device.getEvent();
Event destination = ( Event ) source.clone();
device.destroyEvent();
return destination;
}
/**
* サーバに対して情報を送信する
* @param message メッセージ
*/
private void communicate( String message ) throws Exception {
System.err.println( "\t/*** DEBUG ***/ connecting... hostName=" + hostName + " portNumber=" + portNumber );
Client client = new Client();
client.setEncoding( encoding );
client.communicate( hostName, portNumber, message );
}
/** 単体試験 */
static public void main( String[] args ) {
Procedure registration = new Procedure( "登録" );
Procedure inspection = new Procedure( "検査" );
Device readerA = new Device( "読取装置A", 1 );
Device readerB = new Device( "読取装置B" , 2 );
Agent agent = new Agent();
agent.getProperties();
agent.addDevice( readerA );
agent.addDevice( readerB );
agent.start();
User user1 = new User( 1, "岸 康弘" );
User user2 = new User( 2, "山田 太郎" );
user1.operate( readerA, registration );
user2.operate( readerB, inspection );
}
}
::::::::::::::
Client.java
::::::::::::::
package AgentBasedTracker;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class Client {
private String encoding;
private int bufferSize = 2048;
public void setEncoding( String encoding ) {
this.encoding = encoding;
}
public void communicate( String hostName, int portNumber, String message ) throws Exception {
InetSocketAddress address = new InetSocketAddress( InetAddress.getByName( hostName ), portNumber );
SocketChannel channel = SocketChannel.open(); // オープン
channel.connect( address ); // サーバに接続
Charset charset = Charset.forName( encoding );
ByteBuffer request = charset.encode( message );
channel.write( request ); // 書き込み
ByteBuffer response = ByteBuffer.allocate( bufferSize );
channel.read( response ); // 読み込み
response.flip();
System.out.println( "サーバ側からの応答: " + charset.decode( response ) );
channel.close();
}
static public void main( String[] args ) throws Exception {
Client client = new Client();
client.setEncoding( "Shift_JIS" );
client.communicate( "192.168.0.2", 80, "今晩は!" );
}
}
::::::::::::::
Device.java
::::::::::::::
package AgentBasedTracker;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class Device {
private Agent agent;
private String name;
private int id;
private Event event = null;
public Device( String name , int id ) {
this.name = name;
this.id = id;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void createEvent() {
event = new Event();
}
public void destroyEvent() {
event = null;
}
public boolean hasEvent() {
return ( event != null );
}
public Event getEvent() {
return event;
}
public void setAgent( Agent agent ) {
this.agent = agent;
}
}
::::::::::::::
Event.java
::::::::::::::
package AgentBasedTracker;
/**
*
* $Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*
* @author KISHI Yasuhiro
*/
public class Event implements Cloneable {
Operator operator;
Procedure procedure;
/**
* 誰が操作したのかをセットする
* @param operator 操作者
*/
public void setOperator( Operator operator ) {
this.operator = operator;
}
public Operator getOperator() {
return operator;
}
public void setProcedure( Procedure procedure ) {
this.procedure = procedure;
}
public Procedure getProcedure() {
return procedure;
}
public Object clone() {
return this;
}
}
::::::::::::::
EventGenerator.java
::::::::::::::
package AgentBasedTracker;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
@author KISHI Yasuhiro
*/
::::::::::::::
GenericUtils.java
::::::::::::::
package AgentBasedTracker;
import java.util.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class GenericUtils {
/** 引数で与えた時刻からYYYY-MM-DD形式で日付を得る
@param date 実行日付
@return YYYY-MM-DDで整形された日付
*/
static public String getYYYYMMDD( Calendar date ) {
int yy = date.get( Calendar.YEAR );
int mm = date.get( Calendar.MONTH ) + 1;
String mm_str = ( mm < 10 ) ? "0" + String.valueOf( mm ) : String.valueOf( mm );
int dd = date.get( Calendar.DATE );
String dd_str = ( dd < 10 ) ? "0" + String.valueOf( dd ) : String.valueOf( dd );
return yy + "-" + mm_str + "-" + dd_str;
}
/** 引数で与えた時刻からHH:MI:SS形式で時刻を得る
@param date 実行日付
@return HH:MM:SSで整形された時刻
*/
static public String getHHMISS( Calendar date ) {
int hh = date.get( Calendar.HOUR_OF_DAY ); // 24時間制の場合
String hh_str = ( hh < 10 ) ? "0" + String.valueOf( hh ) : String.valueOf( hh );
int mi = date.get( Calendar.MINUTE ) ;
String mi_str = ( mi < 10 ) ? "0" + String.valueOf( mi ) : String.valueOf( mi );
int ss = date.get( Calendar.SECOND );
String ss_str = ( ss < 10 ) ? "0" + String.valueOf( ss ) : String.valueOf( ss );
return hh_str + ":" + mi_str + ":" + ss_str;
}
}
::::::::::::::
Operator.java
::::::::::::::
package AgentBasedTracker;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public abstract class Operator {
protected int id;
protected String name;
protected Operator( int id, String name ) {
this.id = id;
this.name = name;
}
protected String getName() {
return name;
}
protected int getId() {
return id;
}
/**
* 指定したデバイスにて操作する
*/
abstract public void operate( Device device, Procedure procedure );
}
::::::::::::::
Procedure.java
::::::::::::::
package AgentBasedTracker;
import java.util.*;
import java.io.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
*/
public class Procedure extends AbstractProcedure {
public Procedure( String name ) {
super( name );
}
}
::::::::::::::
Server.java
::::::::::::::
package AgentBasedTracker;
import java.io.*;
import java.net.*;
import java.util.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
/**
$Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class Server {
/** 受付番号 */
private static int receptionNumber = 0;
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private int bufferSize = 2048;
private int portNumber;
private String encoding;
/** プロパティファイルのPATH */
private String propFileName = "./server-config.xml";
public void getProperties() {
// プロパティをロードする
Properties prop = new Properties();
try {
InputStream stream = new FileInputStream( propFileName );
prop.loadFromXML( stream );
stream.close();
// 一覧を出力
prop.list( System.out );
//=========================================================
// 各プロパティを取得
//=========================================================
portNumber = new Integer( prop.getProperty( "portNumber" ) ).intValue();
encoding = prop.getProperty( "messageEncoding" );
} catch ( IOException e ) {
e.printStackTrace();
System.err.println( propFileName + "が見つかりません!" );
System.exit( 1 );
}
}
public void init() throws Exception {
// プロパティの取得
getProperties();
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking( false ); // 非同期モードにする
InetSocketAddress address = new InetSocketAddress( InetAddress.getLocalHost(), 80 );
serverSocketChannel.socket().bind( address );
serverSocketChannel.register( selector, SelectionKey.OP_ACCEPT );
}
public void invoke() throws Exception {
System.out.println();
System.out.println( "Server started..." );
System.out.println();
while ( selector.select() > 0 ) {
Set keys = selector.selectedKeys();
Iterator keyIterator = keys.iterator();
while ( keyIterator.hasNext() ) {
SelectionKey key = ( SelectionKey ) keyIterator.next();
keyIterator.remove(); // 選択されたキーを削除
if ( key.isAcceptable() ) {
ServerSocketChannel serverChannel = ( ServerSocketChannel ) key.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.configureBlocking( false ); // 非同期に変更
socketChannel.register( selector, SelectionKey.OP_READ );
System.out.println( socketChannel + " connect." );
} else if ( key.isReadable() ) {
SocketChannel channel = ( SocketChannel ) key.channel();
communicate( channel );
}
}
}
serverSocketChannel.close();
}
private void communicate( SocketChannel socketChannel ) throws Exception {
try {
Object lock = new Object()
;
Charset charset = Charset.forName( encoding );
// クライアントからのリクエストを読み込む
ByteBuffer request = ByteBuffer.allocate( bufferSize );
socketChannel.read( request );
request.flip();
System.out.println();
System.out.print( "時刻: " + ( new Date() ).toString() );
System.out.println();
System.out.println( "[クライアントからの要求電文]\n" + charset.decode( request.duplicate() ) );
synchronized ( lock ) {
receptionNumber ++;
System.out.println( "この要求の受付番号=" + receptionNumber );
}
// 返信メッセージを返す
ByteBuffer response = charset.encode( "受け取りました! 受付番号=" + receptionNumber );
socketChannel.write( response );
socketChannel.close();
} catch ( Exception e ) {
return ;
}
}
static public void main( String[] args ) {
Server server = new Server();
try {
server.init();
server.invoke();
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
::::::::::::::
User.java
::::::::::::::
package AgentBasedTracker;
/**
* $Id: Agent.html,v 1.1 2009/06/22 16:11:36 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class User extends Operator {
public User( int id, String name ) {
super( id, name );
}
/**
* デバイスを操作する⇒デバイスがイベントを生成する
* @param device 操作するデバイス
*/
public void operate( Device device, Procedure procedure ) {
// 操作する際の個人差などを個別に実装する ---> 機械との違いなど
// (未実装)
device.createEvent();
// 操作者として自身をセット ⇒ イベントと操作者の紐付け
Event event = device.getEvent();
event.setOperator( this );
event.setProcedure( procedure );
}
}
戻る