Agent Village 〜 エージェントの里 〜

Minor Menu : [ インデックス ] [ Round01 ] [ Round02 ]

JADEチュートリアル - Round 02 :
ピンと言えばポンと答える

概要

このチュートリアルでは複数のエージェント間で簡単な対話をさせてみます。対話手順としてFIPA仕様の会話プロトコル(インタラクション・プロトコル)の中でもっとも代表的でもっとも良く使われるプロトコルであるREQUESTインタラクション・プロトコルを使用します。これによって次の知識が得られます。

  • FIPAインタラクション・プロトコル仕様の読み方
  • JADEでのREQUESTインタラクション・プロトコルの利用法
  • プラットフォームを跨る(リモートにある)エージェントへのメッセージ送信の仕方

これによって次のことができるようになります。

  • 複数のエージェント間で簡単な対話を行わせる。
  • ノードを越えたリクエストの送受信。
  • FIPA仕様に対する理解を深める。

↑先頭に戻る↑

準備

まず、このチュートリアルをはじめるために必要な環境を準備します。以下の手順に従って必要なものを用意してください(すでにインストールされている項目は適宜飛ばしてください)。

  1. Java開発環境(J2SDK 1.4以上)のインストール
  2. パッケージのダウンロードやインストール方法などについてはJavaホームページ<http://java.sun.com>等をご覧ください。

  3. ANTのインストール
  4. パッケージのダウンロードやインストール方法などについてはANTホームページ<http://ant.apache.org/>等をご覧ください。なお、ANTはサンプル・コードのビルドや実行を簡単にするために利用しますが必須ではありません(同等の事はすべてコマンド・ラインからでも実行できます)。

  5. JADEのインストール
  6. JADEのインストール方法は【JADE - インストール】のページをご覧ください。以降ではJADEのインストール先ディレクトリを JADE_HOME と記します。

  7. サンプル・ファイルのダウンロードと展開
  8. サンプル・ファイル(JADETutorial02.zip, 11,068 Bytes)をここからダウンロードして各自の作業に適したディレクトリに展開してください。サンプル・ファイルを展開するとJADETutorial02というディレクトリができます。以降ではこのディレクトリを SAMPLE_HOME と記します。

  9. JADE本体のjarファイルをコピー
  10. JADE_HOME/lib にある5つのjarファイル(Base64.jar, http.jar, iiop.jar, jade.jar, jadeTools.jar)を SAMPLE_HOME/lib/JADE ディレクトリの下にコピーします。

  11. サンプル・コードのビルド(※1)
  12. カレント・ディレクトリを SAMPLE_HOME に移し、"ant build" コマンドを実行します(antコマンドが実行パス中に含まれていることを前提にしています)。ビルドが成功すると "BUILD SUCCESSFUL" というメッセージが表示され、SAMPLE_HOME/bin ディレクトリが生成され、そこにコンパイル済みのクラス・ファイルが置かれます。図1にWindowsのコマンド・プロンプトからビルドを実行した際の様子を示します。

    図1 : サンプル・コードのビルド
    SAMPLE_HOME\> ant build
    Buildfile: build.xml
    
    init:
    
    compile:
        [mkdir] Created dir: SAMPLE_HOME\bin
        [javac] Compiling 4 source files to SAMPLE_HOME\bin
    
    resource:
    
    build:
    
    BUILD SUCCESSFUL
    Total time: 2 second
※1

サンプル・ファイルには Eclipse 3.x 用のプロジェクト定義ファイル(.classpath, .project)も付属してあるので、SAMPLE_HOME ディレクトリをEclipseのプロジェクトとしてインポートしてビルド/編集することもできます。

↑先頭に戻る↑

仕様書を覗いてみる

インタラクション・プロトコル(Interaction Protocol)とは、エージェント間で交わされる対話の典型的な手順をまとめたものです。FIPAによって規定されているインタラクション・プロトコルの一覧は【FIPA - IP (Interaction Protocol)】のページをご覧ください。

インタラクション・プロトコルは何種類か定義されているのですが、このチュートリアルではそのうちもっとも良く使われる一般的な処理要求を行う手順であるREQUESTインタラクション・プロトコルを利用してみます。REQUESTインタラクション・プロトコルの詳しい仕様はFIPA仕様の "00026: FIPA Request Interaction Protocol Specification" に記されています。この仕様書を見てみると図2のような少し変わった感じのシーケンス図が描かれています(図2ではさらに適当な箇所にコメントを入れています)。

図2 : FIPA Request Interaction Protocol (Main Flow)

図2のシーケンス図はAUMLというUMLの拡張表記形式で記述されているのですが、細かいところを気にしなければ「だいたいどんな対話手順になっているか」というのが読み取れるかと思います。一応、この流れを順に追っていってみましょう。

  1. まず、InitiatorParticipantに対して何らかのリクエスト・メッセージを送ります。このACLメッセージのprotocolスロットにはfipa-requestが、performativeスロットにはrequestが、それぞれ設定されていなければなりません。
  2. Participantが要求された処理の実行を却下する場合、Initiatorに対してrefuseメッセージ(performativeスロットにrefuseが設定されたACLメッセージ)が返され、このリクエスト・シーケンスは終了します。
  3. Participantは受け付けた処理に時間がかかる場合など、必要に応じてInitiatorに対してagreeメッセージを返します(「リクエストは受け付けたけどちょっと待ってね」といった感じ)。このagreeメッセージの返信は省略されることがあります。
  4. Participantは要求された処理を実行し、実行に成功した場合はinformメッセージを(実行に失敗した場合はfailureメッセージを)Initiatorに対して返信して、このリクエスト・シーケンスを終了します。

↑先頭に戻る↑

JADEでのRequestインタラクション・プロトコルのハンドリング

JADEには前述のREQUESTインタラクション・プロトコルを含む「REQUESTライクな」プロトコル群(fipa-request, fipa-query, fipa-request-when, fipa-brokering, fipa-recruiting)の手順制御をやってくれる便利なBehaviourが用意されています。リクエストを発する側のエージェント(Initiator)のためのBehaviourがAchieveREInitiator(またはSimpleAchieveREInitiator)で、リクエストを受け付ける側のエージェント(ParticipantまたはResponder)のためのBehaviourがAchieveREResponder(またはSimpleAchieveREResponder)です。頭に"Simple〜"と付いているモノはリクエスト先のエージェントが1つの場合(良くある普通のリクエスト)用の簡易版で、そうでないモノは同時に複数のエージェントに同じリクエストを投げる場合にも対応できるようになっています。ちなみに、"RE"は"Rational Effect"の略で、全体で「合理的な効果を成し遂げる振る舞い」といった感じの名前になっています。

コトバ(日本語)で説明しても解りにくいのでサンプル・コードを見ながらこれらのBehaviourの使い方を理解していきましょう。

↑先頭に戻る↑

EchoClientエージェント(Initiator側)

SAMPLE_HOME\src\com\mamezou\nappa\sample\echoフォルダの下にEchoClient.javaファイルがありますから、これを適当なエディタなどで開いてみてください。これは前回の【Round01】で作成したEchoServerエージェントに対してリクエスト・メッセージを作って投げるエージェントで、簡単なGUIを備えています。

このソース・コード中でSimpleAchieveREInitiatorを使っている部分を抜粋してリスト1に示します。

リスト1 : EchoClient#sendMessage(String)
/**
 * EchoServerにメッセージを送る。
 * 
 * @param message 送信するメッセージ文字列。
 */
protected void sendMessage( String message ) {
    ACLMessage request = new ACLMessage( ACLMessage.REQUEST ) ; // 送信メッセージの作成
    request.setProtocol( FIPANames.InteractionProtocol.FIPA_REQUEST ) ; // プロトコルの指定
    request.addReceiver( new AID( DEFAULT_SERVER_AGENT_NAME ,
            AID.ISLOCALNAME ) ) ; // メッセージ送信先の指定
    // TODO メッセージ送信先のエージェント名を起動時の引数で指定できるようにしてみよう
    request.setContent( message ) ; // メッセージ内容の設定
    // メッセージ内容に日本語を入れて通すためのおまじない
    Envelope envelope = request.getEnvelope() ;
    if ( envelope == null ) {
        request.setDefaultEnvelope() ;
        envelope = request.getEnvelope() ;
    }
    envelope.setPayloadEncoding( "UTF-8" ) ;
    // FIPA Request Interaction ProtocolのInitiatorを作成し自身に登録
    this.addBehaviour( new SimpleAchieveREInitiator( this , request ) {
        protected void handleInform( ACLMessage inform ) {
            // (EchoServerから)INFORMを受け取ったときに呼び出される
            gui.responseTextArea.setCaretPosition( gui.responseTextArea.getText().length() ) ;
            gui.responseTextArea.append( "【" + inform.getSender().getName()
                    + "】 " + inform.getContent() + "\n" ) ;
        }
        // TODO メッセージの送信に失敗したときのハンドラを追加してみよう
    } ) ;
}

EchoClient#sendMessage(String)メソッドはGUIの「Send」ボタンが押される都度呼び出されるのですが、その中では毎回リクエスト・メッセージを作成し、そのリクエスト・メッセージをコンストラクタで引き渡したSimpleAchieveREInitiatorの匿名インナークラスのインスタンスを生成して#addBehaviour()でエージェントのタスク・リストに追加して終わっています。ここで追加されたBehaviourは(そのうち)エージェント・スレッドによって活性化され実行されることになります。このBehaviourはプロトコル手順を完了するかタイムアウトすると終了してエージェントのタスク・リストから自動的に消えます。

実際にメッセージを送信する処理や返答を待ち受ける部分などの厄介な処理はすべてSimpleAchieveREInitiatorで記述されているので、そちらにお任せしてしまえば十分です。ここでは、いくつか用意されているフック・メソッドのひとつである#handleInform()をオーバーライドして、informメッセージが返信されてきたらGUIにその結果を表示するようにしています。SimpleAchieveREInitiatorで用意されているフック・メソッド(ハンドラ・メソッド)の一覧を表1に示します(AchieveREInitiatorもほぼ同様のフック・メソッドを備えています)。

表1 : jade.proto.SimpleAchieveREInitiatorに用意されているフック・メソッドの一覧
メソッド名解説
#handleAgree(ACLMessage message) agreeメッセージが返信されてきた時に呼び出される。
#handleAllResponses(Vector messages) すべての"responses"メッセージ(agree, refuse, not-understood)が集められた時かタイムアウトした時に呼び出される。
#handleAllResultNotifications(Vector messages) すべての"result notification"メッセージ(inform, failure)が集められた時かタイムアウトした時に呼び出される。
#handleFailure(ACLMessage message) failureメッセージが返信されてきた時に呼び出される。
#handleInform(ACLMessage message) informメッセージが返信されてきた時に呼び出される。
#handleNotUnderstood(ACLMessage message) not-understoodメッセージが返信されてきた時に呼び出される。
#handleOutOfSequence(ACLMessage message) プロトコル・ルールに従わないメッセージを受け取った時に呼び出される。
#handleRefuse(ACLMessage message) refuseメッセージが返信されてきた時に呼び出される。

↑先頭に戻る↑

EchoServerエージェント(Responder側)

EchoClientに合わせてEchoServer側もSimpleAchieveREResponderを使ってリクエストを受け付けるように改造します。SAMPLE_HOME\src\com\mamezou\nappa\sample\echoフォルダの下のEchoServer.javaファイルが改造後のソースなので、適当なエディタなどで開いてみてください。

このソース・コード中でSimpleAchieveREResponderを使っている部分を抜粋してリスト2に示します。

リスト2 : EchoServer#setup()
protected void setup() {
    super.setup() ;
    // REQUESTメッセージにマッチするメッセージ・テンプレートを作成する。
    MessageTemplate template =
        SimpleAchieveREResponder.createMessageTemplate( FIPANames.InteractionProtocol.FIPA_REQUEST ) ;
    this.addBehaviour( new SimpleAchieveREResponder( this , template ) {
        protected ACLMessage prepareResponse( ACLMessage request )
                throws NotUnderstoodException , RefuseException {
            // テンプレートに合致するメッセージが届いた時に呼び出されるハンドラ・メソッド。
            String content = request.getContent() ;
            Logger.getLogger( "com.mamezou.nappa.sample.echo" ).info(
                request.getSender().getName()
                        + " sends a request message with \"" + content
                        + "\"." ) ;
            // REQUESTメッセージに対応する返信メッセージを作成する(この場合はINFORM)。
            ACLMessage reply = request.createReply() ;
            reply.setPerformative( ACLMessage.INFORM ) ;
            reply.setContent( "Echo: " + request.getContent() ) ;
            // メッセージ内容に日本語を入れて通すためのおまじない
            Envelope envelope = reply.getEnvelope() ;
            if ( envelope == null ) {
                reply.setDefaultEnvelope() ;
                envelope = reply.getEnvelope() ;
            }
            envelope.setPayloadEncoding( "UTF-8" ) ;
            // 作成したメッセージを返してあげればフレームワーク側でメッセージ送信や後始末をやってくれる。
            return reply ;
        }
        // TODO 一度AGREEメッセージを返し、しかる後に結果をINFORMメッセージで返すようにしてみよう。
    } ) ;
}

Responder側のBehaviour(SimpleAchieveREResponder)は常にクライアントからのリクエストを待ち受けている必要があるので、#setup()で生成してエージェントのタスク・リストに追加しておきます。このBehaviourはあるクライアントからのリクエスト処理手順を終えると自動的にリクエスト待ちの状態に戻ります。明示的にタスク・リストから削除しない限り、自動的に終了して消えるようなことはありません。

ここではEchoClientと同様にSimpleAchieveREResponderの匿名インナークラスのインスタンスを生成して自身のタスク・リストに登録していますが、それに先立ってメッセージ・テンプレートというオブジェクトを作ってコンストラクタに引き渡しています。このメッセージ・テンプレートは一種のフィルタ・パターンで、エージェントのメッセージ・キューに入っている特定のACLメッセージにマッチする条件を表現しています。このサンプルでは、protocolスロットに"fipa-request"が、performative"request"が設定されているACLメッセージにマッチするパターンを作っています(実際にこのパターンを作っているのはSimpleAchieveREResponder#createMessageTemplate()メソッドの中)。このようなメッセージ・テンプレートを指定することによって、SimpleAchieveREResponderはエージェントのメッセージ・キューに入ってきている様々なメッセージの中から自分が処理すべきメッセージを見つけ出すことができるわけです。

サンプル・コードでは、いくつか用意されているフック・メソッドのうちSimpleAchieveREResponder#prepareResponse()メソッドだけをオーバーライドして返答メッセージ(informメッセージ)を生成して返信しています。SimpleAchieveREResponderで用意されているフック・メソッドの一覧を表2に示します(AchieveREResponderもほぼ同様のフック・メソッドを備えています)。

表2 : jade.proto.SimpleAchieveREResponderに用意されているフック・メソッドの一覧
メソッド名解説
#prepareResponse(ACLMessage request) メッセージ・テンプレートに合致したメッセージを受信した時に呼び出される応答メッセージ(agree, refuse, not-understood)準備用のフック・メソッド。この時点でいきなり返答メッセージ(inform)を返しても良い。デフォルトの実装ではnullを返す(応答メッセージを返信しない)。
#prepareResultNotification(ACLMessage request, ACLMessage response) 返答メッセージ(inform, failure)準備用のフック・メソッド。Initiatorから送られたリクエスト・メッセージと事前に返信した応答メッセージ(応答メッセージを返信していない場合はnull)を引数に取り、リクエストされた何らかの処理を実行し、その結果を返答メッセージとして返す。デフォルトの実装ではnullを返す(Initiatorに返答メッセージを返信しない)ので、少なくとも#prepareResponse()#prepareResultNotification()のどちらか一方をオーバーライドして返答メッセージを返すようにする必要がある。

↑先頭に戻る↑

EchoServerとEchoClientを動かしてみる

では、実際にEchoServerEchoClientを動かして動作を観察してみましょう。

カレント・ディレクトリを SAMPLE_HOME に移し、コマンド・プロンプトから図3のように "ant run-EchoServerAndClient" コマンドを実行してください。

図3 : EchoServerとEchoClientを動かしてみる
SAMPLE_HOME\> ant run-EchoServerAndClient
Buildfile: build.xml

init:

compile:

resource:

build:

run-rma:
     [java]     This is JADE 3.2 - 2004/07/26 13:41:05
     [java]     downloaded in Open Source, under LGPL restrictions,
     [java]     at http://jade.cselt.it/

     [java] http://hostname:7778/acc
     [java] Agent container Main-Container@JADE-IMTP://hostname is ready.

しばらくすると、【Round01】でも見た RMA (Remote Management Agent) の画面と一緒に図4のようなEchoClientのGUI画面が表示されます。

図4 : EchoClientのGUI画面

EchoClientのGUI画面の下側のテキスト・フィールドに適当な文字列を入力して「Send」ボタンを押すと、メッセージがEchoServerに送信されて、その返答が上側のテキスト・フィールドに表示されます(図5)。

図5 : EchoClientのGUI画面(適当に入力してみた)

このメッセージ送受信の様子はSnifferツールを使って視覚的に確認することができます(図6)。Snifferの使い方については【Round01】や【JADE - ツール - Sniffer】をご覧ください。

図6 : Snifferでメッセージ送受信を観察してみる
※2: Conversation-id

図6のSnifferの画面表示で興味深いのは、対になるリクエストと返答メッセージが同じ色の矢印で表示されている点です。これは偶然なのでしょうか? この秘密はSnifferの画面でメッセージの矢印をダブル・クリックして各々のメッセージの内容をよく調べてみると判ります。

このサンプルでやり取りされた各々のメッセージのConversation-idスロットにはC28487985_1101209444125といった感じのIDが自動的に設定されています(このIDの管理やハンドリングはSimpleAchieveREInitiatorSimpleAchieveREResponderが裏でやってくれています)。これは一連の対話(このサンプルではrequestインタラクション・プロトコルの一連の流れ)に対して割り振られたユニークなIDで、同じ対話に含まれる各々の発話(メッセージ)には同じConversation-idが振られます。これによって、エージェントはバラバラに送られてくるメッセージがどの対話シーケンスに含まれているものであるか特定することができます。

SnifferはこのようなFIPA仕様の特性を利用して、同じ対話に含まれるメッセージ線を同じ色で表示して見やすくしているわけです。

↑先頭に戻る↑

ピンポン・サンプル

サンプル・コードにはEchoClient/EchoServerと似たようなPingAgent/PongAgentというペアのエージェントが用意されています。PongAgentの方がサーバ(Responder側)でPingAgentの方がクライアント(Initiator側)です。

PongAgentは自分が知っているキーワードでリクエストされると、それに対応する合言葉を返答してきます。たとえば、「ピン」と言えば「ポン」と答え、「山」と言えば「川」と答える…といった感じです。PongAgentがどんなキーワードを知っているかはソース・コードを覗いてみてください。PongAgentはリクエストされたキーワードに対して、自分の知っているキーワードであればagreeメッセージを返答し、そうでなければrefuse(却下)メッセージを返答します。その後(agreeだった場合)、あらためて対応する合言葉をinformメッセージとして返信してきます。この手順はFIPAのREQUESTインタラクション・プロトコルに合致しています。

↑先頭に戻る↑

ピンポン・サンプルの実行

では、実際にPingAgentPongAgentを動かして動作を観察してみましょう。

カレント・ディレクトリを SAMPLE_HOME に移し、コマンド・プロンプトから図7のように "ant run-PingAndPongAgent" コマンドを実行してください。

図7 : PingAgentとPongAgentを動かしてみる
SAMPLE_HOME\> ant run-PingAndPongAgent
Buildfile: build.xml

init:

compile:

resource:

build:

run-PingAndPongAgent:
     [java]     This is JADE 3.2 - 2004/07/26 13:41:05
     [java]     downloaded in Open Source, under LGPL restrictions,
     [java]     at http://jade.cselt.it/

     [java] http://hostname:7778/acc
     [java] Agent container Main-Container@JADE-IMTP://hostname is ready.

しばらくすると、【Round01】でも見た RMA (Remote Management Agent) の画面と一緒に図8のようなPingAgentのGUI画面が表示されます。

図8 : PingAgentのGUI画面

この画面はEchoClientのGUI画面とよく似ていて使い方もほとんど同じですが、画面の上側にサーバのエージェント名(グローバル名)とプラットフォームのアドレスを指定する欄が増えている点が少し違います。実際にメッセージを送る前に、「Agent GUID」と「Platform Address」の欄の「hostname」となっている箇所を実際のホスト名に書き換えてください。あとはEchoClientのGUIと同じような感じでSnifferなども併用しながらメッセージの送受信の様子を確かめながらいろいろ入力してみてください(図9)。

図9 : PingAgentのGUI画面(適当に入力してみた)

↑先頭に戻る↑

プラットフォームを越えたメッセージ送受信

さて、ここまでは1台のPCの上でサーバ(Responder)とクライアント(Initiator)を動作させてメッセージ送受信をやってきましたが、せっかくJADEのような分散環境を使っているので、そろそろプラットフォーム(ノード)を越えたメッセージ送受信を試してみましょう。ネットワークで繋がった2台以上のPCが使える方は是非試してみてください。

この例では、"ICHIYOU"というPCでPongAgent(サーバ(Responder)側)を、"KITSUNE-PRONOTE"というPCでPingAgent(クライアント(Initiator)側)を、それぞれ立ち上げてメッセージが送られる様子を確認してみます。

まず、サーバ側(この例では"ICHIYOU"というPC)でカレント・ディレクトリを SAMPLE_HOME に移し、コマンド・プロンプトから図10のように "ant run-PongAgent" コマンドを実行してください。

図10 : PongAgentを起動する(サーバ側)
SAMPLE_HOME\> ant run-PongAgent
Buildfile: build.xml

init:

compile:

resource:

build:

run-PongAgent:
     [java]     This is JADE 3.2 - 2004/07/26 13:41:05
     [java]     downloaded in Open Source, under LGPL restrictions,
     [java]     at http://jade.cselt.it/

     [java] http://hostname:7778/acc
     [java] Agent container Main-Container@JADE-IMTP://hostname is ready.

次に、クライアント側(この例では"KITSUNE-PRONOTE"というPC)でカレント・ディレクトリを SAMPLE_HOME に移し、コマンド・プロンプトから図11のように "ant run-PingAgent" コマンドを実行してください。

図11 : PingAgentを起動する(クライアント側)
SAMPLE_HOME\> ant run-PingAgent
Buildfile: build.xml

init:

compile:

resource:

build:

run-PingAgent:
     [java]     This is JADE 3.2 - 2004/07/26 13:41:05
     [java]     downloaded in Open Source, under LGPL restrictions,
     [java]     at http://jade.cselt.it/

     [java] http://hostname:7778/acc
     [java] Agent container Main-Container@JADE-IMTP://hostname is ready.

クライアント側にはPingAgentのGUI画面が開くので、この画面の上部の"Agent GUID""Platform Address"欄の中のホスト名の部分をサーバのホスト名に書き換え、あとはローカルでやっていたのと同様に画面下部のRequestの欄に適当な文字列を書き込んで「Send」ボタンを押すとメッセージの送受信が行われます(図12)。

図12 : PingAgentのGUI画面(リモートのPongAgentとの通信)

この時、クライアント側でSnifferを起動してPingAgentのメッセージを監視すると(図13)のように、また、サーバ側でもSnifferを起動してPongAgentのメッセージを監視すると(図14)のように、それぞれプラットフォームの外(Sniffer画面中でOtherと表示されているところ)から(または外へ)のメッセージ送受信が行われているのが観察できます。

図13 : Sniffer画面(PingAgentの監視)
図14 : Sniffer画面(PongAgentの監視)

コード中では、エージェントがローカルに居る(同じプラットフォーム上で動作している)かリモートに居る(別のプラットフォーム上で動作している)かはほとんど意識していません。唯一の違いはACLメッセージの宛先となるAID(AgentID)の作り方の部分で、相手のエージェントがローカルに居る場合はリスト3のようにエージェントのニックネームだけを指定してAIDを生成していたのに対して、リモートに居るエージェントを指定する場合はリスト4のように GUID ("Global Unique ID"の略で "エージェント名@ホスト名:1099/JADE" といった感じで大域的にユニークになるように付けられたエージェント名) とプラットフォームのアドレス(この例では HTTP MTP (Message Transport Protocol) を使っているので "http://ホスト名:7778/acc" といった感じのURLになる)を指定してグローバルなAIDを生成しています。

リスト3 : ローカルなAIDの生成
AID receiverAID = new AID( "PongAgent" , AID.ISLOCALNAME ) ;
リスト4 : グローバルなAIDの生成
AID receiverAID = new AID( "PongAgent@hostname:1099/JADE" , AID.ISGUID ) ;
receiverAID.addAddresses( "http://hostname:7778/acc" ) ;

要は、相手エージェントのグローバルな名前とアドレスさえ判明すれば(※3)ホストを越えたリクエストの送受信ができてしまうのです。どうです? なんだかとってもお手軽じゃないですか?

※3

正確には通信するプラットフォーム間でお互いにサポートするMTP(Message Transport Protocol)が合致している必要があります。この例では双方のプラットフォームが HTTP MTP (JADE 3.2 以降のデフォルトMTP) を使っているので特に問題なくメッセージの送受信が行われています。FIPA準拠のエージェント・プラットフォームでは複数種類のMTPをサポートする(プラグインする)ことができるような仕様になっています。

↑先頭に戻る↑

まとめ

このチュートリアルでは、FIPA仕様で定義されているインタラクション・プロトコル群のうち、もっとも代表的なREQUESTインタラクション・プロトコルの手順を知り、それをJADE上のエージェント間でどうやって実現(利用)すれば良いのかサンプル・コードを見ながら具体的に学んできました。複数のエージェントの間で会話をさせてみると、だんだん面白いことができるようになってきますね。

次のチュートリアルでは、また別の(そして特徴的な)インタラクション・プロトコルであるSUBSCRIBEインタラクション・プロトコルを利用した具体例を取り上げていきます。このようなBehaviourを自由に使えるようになれば、JADEを活用した本格的なマルチ・エージェント・システムの開発が容易になります。

↑先頭に戻る↑

JADE is a trademark of Telecom Italia Lab.
Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
All other products referred to herein are service names, trademarks or registered trademarks of the companies that own and market those products.