以下如果未特殊声明,都在JADE管理器中运行,然后再Eclipse控制台中查看!
JADE行为类
在前面的例子中,Agent所作的工作都定义在了setup方法中,实际上它具有的行为和执行的动作都应该定义在Behavious类中,我们可以对Behavior类生成实例,然后将任务或者动作代码放在对Behavious类中的action方法中,action方法是必须要有的。Behavious类还有很多子类,分别对应着不同类型的Behaviour,包括SimpleBehaviour,SequencesBehaviour, ParallelBehavior, CyclicBehavior等。
一个Agent的行为表示它能够执行的任务,通过继承jade.core.behaviours.Behaviour来实现。然后在Agent类中通过addBehaviour()方法将行为加入进来。当一个Agent启动(通过setup()方法后,行为可以在任何时间加入进来。
要定义Behaviour必须实现其action()方法,它定义了Agent的执行时的实际动作,而done()方法指名了一个行为是否已执行完毕,是否要从行为池中删除。
一个Agent可以并发执行多个behaviour。每个Agent线程启动后执行的过程如下:

SimpleBehaviour简单行为

下面的例子中我们不在setup()中打印信息,而是把它放在一个简单行为中:
在jadetest包里面新建一个java类命名为HelloWorldBehaviour,输入下面代码。配置中把变量改为-gui sb:jadetest.SimpleBehaviour,运行

  1. package jadetest;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午5:20:11
  7. */
  8. import jade.core.Agent;
  9. import jade.core.Location;
  10. import jade.core.behaviours.SimpleBehaviour;
  11.  
  12. public class HelloWorldBehaviours extends Agent {
  13. public void setup() {
  14. SimpleBehaviour hello_behaviour = new SimpleBehaviour(this) {
  15. boolean finished = false;
  16.  
  17. // 覆盖 Behaviour 类的action这一抽象方法
  18. public void action() {
  19. System.out.println("HelloWorldBehaviour run: Hello World!");
  20. System.out.println("-----About Me:-----");
  21. System.out.println("My local name is:" + getLocalName());
  22. System.out.println("My globally unique name is:" + getName());
  23. System.out.println("-----About Here:-----");
  24. Location l = here();
  25. System.out.println("I am running in a location called:" + l.getName());
  26. System.out.println("Which is identified uniquely as:" + l.getID());
  27. System.out.println("And is contactable at:" + l.getAddress());
  28. System.out.println("Using the protocol:" + l.getProtocol());
  29. finished = true;
  30. }
  31.  
  32. // done()在父类中也是一个抽象方法
  33. public boolean done() {
  34. return finished;
  35. }
  36. };
  37. addBehaviour(hello_behaviour);
  38. } // setup()
  39. }

然后使用智能体管理器添加智能体并运行:

输出结果为:
HelloWorldBehaviour run: Hello World!

-----About Me:-----

My local name is:hwb

My globally unique name is:hwb@172.17.98.217:1099/JADE

-----About Here:-----

I am running in a location called:Main-Container

Which is identified uniquely as:Main-Container@172.17.98.217

And is contactable at:172.17.98.217

Using the protocol:jicp

这个程序相较于前面的例子多了action, done两个函数,它们分别执行自己的操作。HelloWorldBehaviours类加载时定义一个简单行为,这个简单行为执行的操作由action,done来实现。然后,再通过加载语句(addBehaviour(hello_behaviour))执行这个简单行为

简单行为和循环行为(CyclicBehaviour)组合的例子

一个Agent中可以加入各种Behaviour构成CompositeBehaviour。

在Eclipse的jade工程中编写下列程序,过程如前所描述。

  1. package jadetest;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午8:46:29
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.Behaviour;
  10. import jade.core.behaviours.CyclicBehaviour;
  11. import jade.core.behaviours.OneShotBehaviour;
  12.  
  13. public class SimpleAgent extends Agent {
  14. private class FourStepBehaviour extends Behaviour {
  15. // SimpleBehaviour hello_behaviour = new SimpleBehaviour(this){
  16. // 这两条语句有很大不同吗?上面的定义一个新的类,下面的修改了标准行为的执行内容
  17. private int step = 1;
  18.  
  19. public void action() {
  20. switch (step) {
  21. case 1:
  22. System.out.println("Operation 1");
  23. break;
  24. case 2:
  25. System.out.println("Operation 2. Adding one-shot behaviour");
  26. myAgent.addBehaviour(new OneShotBehaviour(myAgent) {
  27. // 增加了一个新的动作,即快照
  28. public void action() {
  29. System.out.println("One-shot");
  30. }
  31. });// myAgent.addbehaviour
  32. break;
  33. case 3:
  34. System.out.println("Operation 3");
  35. break;
  36. case 4:
  37. System.out.println("Operation 4");
  38. break;
  39. }// switch
  40. step++;
  41. } // action
  42.  
  43. public boolean done() {
  44. return step == 5; // 判断语句
  45. }
  46.  
  47. public int onEnd() {
  48. myAgent.doDelete();
  49. System.out.println("Finished!");
  50. return super.onEnd();
  51. }
  52. } // class FourStepBehaviour
  53.  
  54. /** Creates a new instance of SimpleAgent */
  55. protected void setup() {
  56. System.out.println("Agent " + getLocalName() + " started.");
  57. addBehaviour(new CyclicBehaviour(this) { // 增加了一个循环行为
  58. public void action() {
  59. System.out.println("Cycling");
  60. }
  61. }); // //增加的循环行为
  62. // Add the generic behaviour
  63. addBehaviour(new FourStepBehaviour());
  64. }// //setup()
  65. }

输出结果:
Agent sa started.

Cycling

Operation 1

Cycling

Operation 2. Adding one-shot behaviour

Cycling

Operation 3

One-shot

Cycling

Operation 4

Finished!

注意每个Agent内部都有一个ParallelBehaviour,我们如果加入多个behaviour到Agent中,他们会并行执行。behaviours加入到队列的顺序就是他们执行的次序。最后,behaviours可以动态的加入到Agent以及CompositeBehaviour。

总结:每个主体的执行都是从setup() 开始顺序执行的。主体可以执行自定义的行为,如上例中的hello_behaviour ,FourStepBehaviour,也可以执行标准化的行为如OneShotBehaviour。

Agent通讯:ACL(Agent communication language)

JADE的Agent之间进行通信使用的acl语言遵循fipa acl规范。一个acl消息通常包含这些参数:sender:消息的发送者,用Agent标志AID表示; receivers,接受Agent消息的Agent可以是多个;Reply-to,应收到回应的接受者;Performative:标志发送消息的目的,即发送者想要通过发送消息干什么,通常有这样一些常值:REQUEST, INFORM, ACCEPT_PROPOSAL, REJECT_PROPOSAL, PROPOSE;Content,消息的内容;内容语言,比如内容的编码格式;ontology,双方都能够理解的消息内容的概念说明和语义描述。

简单实例

发送者:

  1. package jadetest;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:00:25
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.core.behaviours.Behaviour;
  11. import jade.lang.acl.ACLMessage;
  12.  
  13. public class SimpleSender extends Agent {
  14. protected void setup() {
  15. addBehaviour(new Behaviour(this) {
  16. private boolean finished = false;
  17.  
  18. public void action() {
  19. System.out.println(getLocalName() + ": about to inform bob hello");
  20. // we sleep here to give bob a chance to start.
  21. doWait(5000);
  22. AID r = new AID();// 作用是什么?表示消息的发送者
  23. r.setLocalName("bob");
  24. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  25. // set performative
  26. msg.setSender(getAID());
  27. msg.addReceiver(r);
  28. msg.setContent("Hello_BOB");
  29. send(msg);
  30. System.out.println(getLocalName() + ": Send hello to bob");
  31. System.out.println("the content is:" + msg.getContent()); // finished = true;
  32. doWait(5000);
  33. doDelete();
  34. } // action
  35.  
  36. public boolean done() {
  37. return finished;
  38. }
  39. }); // addbehavior
  40. }// setup
  41. }// Agent

这段代码的主要执行过程为:构建一个AID,以此来指出该消息的目的Agent。这里我们指定目的为一个本地的Agent,名字为bob。建立一个ACL消息标志其performative为INFORM。设定Sender为自身,指定接收者为bob。然后发送消息内容。打印相关信息。
接收者:他的名字必须为bob

  1. package jadetest;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:01:36
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.SimpleBehaviour;
  10. import jade.lang.acl.ACLMessage;
  11.  
  12. public class SimpleReceiver extends Agent {
  13. class DoSimpleReceiveBehaviour extends SimpleBehaviour {
  14. private boolean finished = false;
  15.  
  16. public DoSimpleReceiveBehaviour(Agent Agent) {
  17. super(Agent);
  18. }
  19.  
  20. public void action() {
  21. ACLMessage msg = receive();
  22. if (msg != null) {
  23. System.out.println(getLocalName() + ": received the following message : ");
  24. System.out.println(msg.toString());
  25. finished = true;
  26. myAgent.doDelete();
  27. } else {
  28. System.out.println(getLocalName()
  29. + ":No message received, Blocking the behaviour till one is");
  30. block();
  31. }
  32. }// action
  33.  
  34. public boolean done() {
  35. return finished;
  36. }
  37. }// DoSimpleReceiveBehaviour
  38.  
  39. protected void setup() {
  40. DoSimpleReceiveBehaviour behaviour = new DoSimpleReceiveBehaviour(this);
  41. addBehaviour(behaviour);
  42. }
  43. }// Agent

接收者的代码流程为:添加一个简单行为,这一行为检查现在是否有受到消息,若没有,则执行block()方法组织目前的behaviour执行,直到有新的消息到达。
复杂实例

FIPA定义了一组交互协议,包括FIPA-request, FIPA-query, FIPA-request-when, FIPA-contract-net, FIPA-Iterater-net, FIPA-Auction-English, FIPA-Auction-Dutch.其中:

REQUEST-INFORM:A请求B做一些工作,B可以同意或拒绝。如果B同意,则会去完成并告诉A该工作已经完成。等等。

Query:A想知道一些事情,B可以同意或不同意,并将B的回应告诉A。

Propose:在给定一些precondition的条件下,提出一个proposal去执行某些动作。

在Eclipse中创建文件夹ips:其代码文件有两个,分别为

  1. package ips;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:03:05
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.domain.FIPANames.InteractionProtocol;
  11. import jade.lang.acl.ACLMessage;
  12. import jade.proto.SimpleAchieveREInitiator;
  13.  
  14. public class SimpleRequestInitiator extends Agent {
  15. static class MarriageProposer extends SimpleAchieveREInitiator {
  16. protected MarriageProposer(Agent Agent, ACLMessage msg) {
  17. super(Agent, msg);
  18. }
  19.  
  20. protected void handleAgree(ACLMessage msg) {
  21. System.out.println(myAgent.getLocalName() + ": 吼吼! " + msg.getSender().getLocalName()
  22. + " 已经同意嫁给我了, I'm so excited!");
  23. }
  24.  
  25. protected void handleRefuse(ACLMessage msg) {
  26. System.out.println(myAgent.getLocalName() + ": Oh no! "
  27. + msg.getSender().getLocalName() + " 拒绝了我, i feel sad.");
  28. }
  29.  
  30. protected void handleInform(ACLMessage msg) {
  31. System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
  32. + " has informed me of the status of my request." + " They said : "
  33. + msg.getContent());
  34. }
  35.  
  36. protected void handleNotUnderstood(ACLMessage msg) {
  37. System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
  38. + " has indicated that they didn't understand.");
  39. }
  40.  
  41. protected void handleOutOfSequence(ACLMessage msg) {
  42. System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
  43. + "has sent me a message which I wasn't" + " expecting in this conversation");
  44. }
  45. }
  46.  
  47. protected void setup() {
  48. System.out.println(getLocalName() + ": about to propose marriage to bob ");
  49. doWait(5000); // wait for bob to be started.
  50. ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
  51. AID to = new AID();
  52.  
  53. to.setLocalName("bob");
  54. msg.setSender(getAID());
  55. msg.addReceiver(to);
  56. msg.setContent("Marry Me!");
  57. msg.setProtocol(InteractionProtocol.FIPA_REQUEST);
  58. addBehaviour(new MarriageProposer(this, msg));
  59. }
  60. }

还有:

  1. package ips;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:03:57
  7. */
  8.  
  9. import jade.core.AID;
  10. import jade.core.Agent;
  11. import jade.domain.FIPANames.InteractionProtocol;
  12. import jade.lang.acl.ACLMessage;
  13. import jade.proto.SimpleAchieveREResponder;
  14.  
  15. public class SimpleRequestResponder extends Agent {
  16. static class MarriageResponder extends SimpleAchieveREResponder {
  17. public MarriageResponder(Agent Agent) {
  18. super(Agent, createMessageTemplate(InteractionProtocol.FIPA_REQUEST));
  19. }
  20.  
  21. protected ACLMessage prepareResponse(ACLMessage msg) {
  22. ACLMessage response = msg.createReply();
  23. if (msg.getContent() != null && msg.getContent().equals("Marry Me!")) {
  24. System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
  25. + " has asked me to marry him!");
  26. AID sender;
  27. sender = msg.getSender();
  28. if (sender.getLocalName().equals("baz")) {
  29. response.setPerformative(ACLMessage.AGREE);
  30. System.out.println(myAgent.getLocalName() + ":I'm going to agree.");
  31. } else {
  32. response.setPerformative(ACLMessage.REFUSE);
  33. System.out.println(myAgent.getLocalName() + ":I'm going to turn him down.");
  34. }
  35. } else {
  36. response.setPerformative(ACLMessage.NOT_UNDERSTOOD);
  37. System.out.println(myAgent.getLocalName() + ":I didn't understand what "
  38. + msg.getSender().getLocalName() + " just said to me.");
  39. }
  40. return response;
  41. }
  42.  
  43. protected ACLMessage prepareResultNotification(ACLMessage inmsg, ACLMessage outmsg) {
  44. // what they have asked is now complete (or if it failed)
  45. ACLMessage msg = inmsg.createReply();
  46. msg.setPerformative(ACLMessage.INFORM);
  47. msg.setContent("I Do!");
  48. return msg;
  49. }
  50. }
  51.  
  52. protected void setup() {
  53. System.out.println(getLocalName() + ": I wonder if anybody wants to marry me?");
  54. addBehaviour(new MarriageResponder(this));
  55. }//
  56. }

按照以前记载,先打开GUI管理器,主类依然为jade.Boot,参数为-gui,GUI管理打开之后先建立一个名为bob的Agent,对应的类为ips.SimpleRequestResponder,然后再建立一个名为baz的Agent,对应的类为ips.SimpleRequestInitiator,记住顺序不能变,以下是输出结果:
bob: I wonder if anybody wants to marry me?

baz: about to propose marriage to bob

bob:baz has asked me to marry him!

bob:I'm going to agree.

baz: 吼吼! bob 已经同意嫁给我了, I'm so excited!

baz:bob has informed me of the status of my request. They said : I Do!

上例中,应用了SimpleAchieveREInitiator和SimpleAchieveREResponder两个基类,适用于两个Agent之间的交互。可以看出发起者对于不同的回应有不同的执行动作。

技巧:从AMS中获取所有Agent的AID。

  1. package ips;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月16日 下午1:52:33
  7. */
  8. import jade.core.Agent;
  9. import jade.domain.AMSService;
  10. import jade.domain.FIPAAgentManagement.AMSAgentDescription;
  11. import jade.domain.FIPAAgentManagement.SearchConstraints;
  12. import jade.lang.acl.ACLMessage;
  13.  
  14. public class AMSDump extends Agent {
  15. protected void setup() {
  16. AMSAgentDescription[] Agents = null;
  17. try {
  18. SearchConstraints c = new SearchConstraints();
  19. c.setMaxResults(new Long(-1));
  20. Agents = AMSService.search(this, new AMSAgentDescription(), c);
  21. } catch (Exception e) {
  22. System.out.println("Problem searching AMS: " + e);
  23. e.printStackTrace();
  24. }
  25.  
  26. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  27. msg.setContent("Ping");
  28. for (int i = 0; i < Agents.length; i++) {
  29. if (Agents[i].getName().equals(getAID())) {
  30. // 如果不是自己则加入到接收者数组中
  31. continue;
  32. }
  33. msg.addReceiver(Agents[i].getName());
  34. }
  35. }
  36. }

ACL高级特性之消息模板:

MessageTemplate class 利用MessageTemplate可以针对ACLMessage的每个属性设置模式,以达到过滤消息的目的。为了可以构建更复杂的匹配规则,多个模式也可以进行and,or,not运算。最有用的一些规则或方法包括:通信行为匹配,发送者匹配,会话ID匹配。
比如MatchPerformative( performative ) 是通信行为的匹配。

这里 performative 可能是:

ACLMessage.INFORM

ACLMessage.PROPOSE

ACLMessage.AGREE

还有发送者匹配MatchSender( AID ),会话匹配MatchConversationID( String ),通信协议匹配MatchProtocol( String ) ,本体匹配MatchOntology( String)。

比如:MessageTemplate mt = MessageTemplate.and( 
               MessageTemplate.MatchPerformative( ACLMessage.INFORM ),

MessageTemplate.MatchSender( new AID( "a1",                                                         AID.ISLOCALNAME))) ;

相当于建立了一个模板,表示消息规则为INFORM行为并且发送者为“a1”。

接收过程如下:ACLMessage msg = receive( mt );

if (msg != null) { ... handle message }

block();

示例:

  1. package jadePrime.acl;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:07:11
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.core.behaviours.CyclicBehaviour;
  11. import jade.lang.acl.ACLMessage;
  12. import jade.lang.acl.MessageTemplate;
  13.  
  14. public class Template extends Agent {
  15. MessageTemplate mt1 = MessageTemplate.and(MessageTemplate.MatchPerformative(ACLMessage.INFORM),
  16. MessageTemplate.MatchSender(new AID("a1", AID.ISLOCALNAME)));
  17.  
  18. protected void setup() {
  19. // Send messages to "a1" and "a2"
  20.  
  21. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  22. msg.setContent("Ping");
  23. for (int i = 1; i <= 2; i++)
  24. msg.addReceiver(new AID("a" + i, AID.ISLOCALNAME));
  25.  
  26. send(msg);
  27.  
  28. // Set-up Behaviour 1
  29.  
  30. addBehaviour(new CyclicBehaviour(this) {
  31. public void action() {
  32. System.out.print("Behaviour ONE: ");
  33. ACLMessage msg = receive(mt1);
  34. if (msg != null)
  35. System.out.println("gets " + msg.getPerformative() + " from "
  36. + msg.getSender().getLocalName() + "=" + msg.getContent());
  37. else
  38. System.out.println("gets NULL");
  39. block();
  40. }
  41. });
  42. // Set-up Behaviour 2
  43. addBehaviour(new CyclicBehaviour(this) {
  44. public void action() {
  45. System.out.print("Behaviour TWO: ");
  46. ACLMessage msg = receive();
  47. if (msg != null)
  48. System.out.println("gets " + msg.getPerformative() + " from "
  49. + msg.getSender().getLocalName() + "=" + msg.getContent());
  50. else
  51. System.out.println("gets NULL");
  52. block();
  53. }
  54. });
  55. }
  56. }
  1. package jadePrime.acl;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月14日 下午9:10:07
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.CyclicBehaviour;
  10. import jade.lang.acl.ACLMessage;
  11.  
  12. public class Responder extends Agent {
  13. protected void setup() {
  14. addBehaviour(new CyclicBehaviour(this) {
  15. public void action() {
  16. ACLMessage msg = receive();
  17. if (msg != null) {
  18.  
  19. ACLMessage reply = msg.createReply();
  20. reply.setPerformative(ACLMessage.INFORM);
  21. reply.setContent(" Gossip.....");
  22. send(reply);
  23.  
  24. reply.setPerformative(ACLMessage.PROPOSE);
  25. reply.setContent(" Really sexy stuff... cheap! ");
  26. send(reply);
  27. }
  28. block();
  29. }
  30. });
  31. }
  32. }

输出结果:
Behaviour ONE: gets NULL

Behaviour TWO: gets 6 from ams=( (action ( agent-identifier :name template@192.168.23.1:1099/JADE  :addresses (sequence http://jacksile:7778/acc )) (ACLMessage) ) (MTS-error ( agent-identifier :name a1@192.168.23.1:1099/JADE ) (internal-error "Agent not found: getContainerID() failed to find agent a1@192.168.23.1:1099/JADE")) )

Behaviour ONE: gets NULL

Base64:发送消息为java序列化对象

在JADE中,支持Agents之间通信的消息内容使用序列化的java对象,对本地应用,特别是所有Agent都用java实现的情况下也是很有用的.

看实例:一个ObjectSender负责发送一个Person对象,ObjectReceiver负责接收后打印出接收到的内容。

源文件:Person.java

  1. package examples.Base64;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:34:47
  7. */
  8. import java.io.Serializable;
  9. import java.util.Date;
  10.  
  11. public class Person implements Serializable {
  12. String name;
  13. String surname;
  14. Date birthdate;
  15. int age;
  16.  
  17. Person(String n, String s, Date d, int a) {
  18. name = n;
  19. surname = s;
  20. birthdate = d;
  21. age = a;
  22. }
  23.  
  24. public String toString() {
  25. return (name + " " + surname + " born on " + birthdate.toString() + " age = " + age);
  26. }
  27. }

文件2:ObjectSender.java

  1. package examples.Base64;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:35:47
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.lang.acl.ACLMessage;
  11.  
  12. import java.io.IOException;
  13. import java.util.Date;
  14.  
  15. public class ObjectSender extends Agent {
  16. protected void setup() {
  17.  
  18. try {
  19. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  20. msg.setContent("Ping");
  21.  
  22. AID personR = new AID("personR", AID.ISLOCALNAME);
  23. msg.addReceiver(personR);
  24. Person p = new Person("Name1", "Surname1", new Date(), 1);
  25. msg.setContentObject(p);
  26. msg.setLanguage("JavaSerialization");
  27. send(msg);
  28. System.out.println(getLocalName() + " sent 1st msg " + msg);
  29.  
  30. send(msg);
  31.  
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35.  
  36. doDelete(); // kill itself because it has completed its task.
  37.  
  38. }
  39.  
  40. }

文件三:ObjectReceiver.java

  1. package examples.Base64;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:37:17
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.CyclicBehaviour;
  10. import jade.lang.acl.ACLMessage;
  11. import jade.lang.acl.UnreadableException;
  12.  
  13. public class ObjectReceiver extends Agent {
  14. protected void setup() {
  15. addBehaviour(new CyclicBehaviour(this) {
  16. public void action() {
  17. try {
  18. ACLMessage msg = blockingReceive();
  19. System.out.println(getLocalName() + " rx msg" + msg);
  20. if ("JavaSerialization".equals(msg.getLanguage())) {
  21. Person p = (Person) msg.getContentObject();
  22. System.out.println(getLocalName() + " 获取Java对象: ");
  23. System.out.println(p.getClass().getName());
  24. System.out.println(p.toString());
  25. }
  26. } catch (UnreadableException e3) {
  27. System.err.println(getLocalName() + " catched exception " + e3.getMessage());
  28. }
  29.  
  30. block();
  31. }
  32. });
  33. }
  34.  
  35. }

外部应用程序调用Agent
JADE2.3以后的版本都提供了in-process接口来实现外部应用程序对Agent的调用。

我们可以通过jade.core.Runtime.instance()来获得jade运行时的一个单独得实例。有两种方法可以用来创建一个jade主容器和一个jade远程容器。主要调用过程如下:

先看简单的例子:

  1. package inprocess;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:48:37
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.SimpleBehaviour;
  10.  
  11. /**
  12. *
  13. * @author Administrator
  14. */
  15. public class CustomAgent extends Agent {
  16.  
  17. public void setup() {
  18. SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
  19. boolean finished = false;
  20.  
  21. public void action() {
  22. System.out.println("Hello World Behaviour run: 你好,世界!");
  23. System.out.println("-----我是:-----");
  24. System.out.println("我的本地名称是:" + getLocalName());
  25. System.out.println("我全局唯一的标志名称为:" + getName());
  26. finished = true;
  27. }
  28.  
  29. public boolean done() {
  30. return finished;
  31. }
  32.  
  33. };
  34. addBehaviour(helloBehaviour);
  35. }
  36.  
  37. }

以上是要调用的Agent类

  1. package inprocess;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:49:43
  7. */
  8.  
  9. import jade.core.Profile;
  10. import jade.core.ProfileImpl;
  11. import jade.core.Runtime;
  12. import jade.wrapper.AgentContainer;
  13. import jade.wrapper.AgentController;
  14.  
  15. public class InprocessTest {
  16.  
  17. public static void main(String args[]) {
  18. try {
  19. Runtime rt = Runtime.instance();
  20. rt.setCloseVM(true);
  21. Profile pMain = new ProfileImpl(null, 8888, null);
  22. System.out.println("Launching a whole in-process platform..." + pMain);
  23. AgentContainer mc = rt.createMainContainer(pMain);
  24. // set now the default Profile to start a container
  25. ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
  26. System.out.println("Launching the Agent container ..." + pContainer);
  27. AgentController custom = mc.createNewAgent("custom", "inprocess.CustomAgent", null);
  28. custom.start();
  29.  
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33.  
  34. }
  35. }// 以上是调用者,在Eclipse中调试通过。

再看一个例子,也是main函数中动态创建Agent的例子。可以通过先创建另一个容器,然后再这个容器中创建Aent。比如:

  1. public static void main(String[] args) {
  2. // TODO code application logic here
  3. Runtime rt = Runtime.instance();
  4. rt.setCloseVM(true);
  5. ContainerController cc = rt.createAgentContainer(new ProfileImpl(false));
  6.  
  7. AgentController pingAgent = null;
  8. try {
  9. // create Agent and start it
  10. (cc.createNewAgent("hello", "jadeclient.HelloWorldAgent", new Object[0])).start();
  11. } catch (Exception e){}
  12. }

可以写如下测试程序,这里用Eclipse平台,一个HelloWorldAgent,他将被动态创建并向主容器中的server发送一个消息:

  1. package jadeclient;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:50:50
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.core.behaviours.SimpleBehaviour;
  11. import jade.lang.acl.ACLMessage;
  12.  
  13. public class HelloWorldAgent extends Agent {
  14. public void setup() {
  15.  
  16. addBehaviour(new SimpleBehaviour(this) {
  17. boolean finished = false;
  18. AID server = new AID("server", AID.ISLOCALNAME);
  19.  
  20. public void action() {
  21. System.out.println("我的本地名称是:" + getLocalName());
  22. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  23. msg.setContent("消息内容");
  24. msg.addReceiver(server);
  25. send(msg);
  26. System.out.println("已经往主容器中的server发送信息#");
  27. block(1000);
  28.  
  29. finished = true;
  30. }
  31.  
  32. public boolean done() {
  33. return finished;
  34. }
  35. });
  36. };
  37. }

而server角色是收到消息后打印出来。

  1. /*
  2. * ReceiverAgent.java
  3. * To change this template, choose Tools | Template Manager
  4. * and open the template in the editor.
  5. */
  6.  
  7. package jadeclient;
  8.  
  9. /**
  10. * @function
  11. * @author Jacksile E-mail:tufujietec@foxmail.com
  12. * @date 2016年1月15日 下午12:51:57
  13. */
  14. import jade.core.Agent;
  15. import jade.core.behaviours.CyclicBehaviour;
  16. import jade.lang.acl.ACLMessage;
  17.  
  18. /**
  19. *
  20. * @author admin
  21. */
  22. public class ReceiverAgent extends Agent {
  23.  
  24. /** Creates a new instance of ReceiverAgent */
  25.  
  26. // 把接收到的信息打印出来
  27. protected void setup() {
  28. addBehaviour(new CyclicBehaviour(this) {
  29. public void action() {
  30. ACLMessage msg = receive();
  31. if (msg != null)
  32. System.out
  33. .println("收到信息 " + myAgent.getLocalName() + " <- " + msg.getContent());
  34. block();
  35. }
  36. });
  37. }
  38.  
  39. }

所有类写完之后,这里运行的时候先打开GUI管理器,然后GUI界面下创建一个名叫server的Agent,其类为jadeclient. ReceiverAgent,然后再创建一个名叫hello的Agent,其类为jadeclient.HelloWorldAgent.,记住,顺序不能变
在GUI界面管理器显示如下,在Eclipse平台中下面显示的是打印出的信息,可见在同一主机的不同容器中Agent通信与在同一容器中通信并无二样。

看一个稍微复杂的例子:

  1. package examples.inprocess;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:53:06
  7. */
  8.  
  9. import jade.core.Profile;
  10. import jade.core.ProfileImpl;
  11. import jade.core.Runtime;
  12. import jade.core.behaviours.CyclicBehaviour;
  13. import jade.wrapper.AgentContainer;
  14. import jade.wrapper.AgentController;
  15.  
  16. public class InProcessTest {
  17.  
  18. // Simple class behaving as a Condition Variable
  19. public static class CondVar {
  20. private boolean value = false;
  21.  
  22. synchronized void waitOn() throws InterruptedException {
  23. while (!value) {
  24. wait();
  25. }
  26. }
  27.  
  28. synchronized void signal() {
  29. value = true;
  30. notifyAll();
  31. }
  32.  
  33. } // End of CondVar class
  34.  
  35. // This class is a custom Agent, accepting an Object through the
  36. // object-to-Agent communication channel, and displying it on the
  37. // standard output.
  38. public static class CustomAgent extends jade.core.Agent {
  39.  
  40. public void setup() {
  41. // Accept objects through the object-to-Agent communication
  42. // channel, with a maximum size of 10 queued objects
  43. setEnabledO2ACommunication(true, 10);
  44.  
  45. // Notify blocked threads that the Agent is ready and that
  46. // object-to-Agent communication is enabled
  47. Object[] args = getArguments();
  48. if (args.length > 0) {
  49. CondVar latch = (CondVar) args[0];
  50. latch.signal();
  51. }
  52.  
  53. // Add a suitable cyclic behaviour...
  54. addBehaviour(new CyclicBehaviour() {
  55.  
  56. public void action() {
  57. // Retrieve the first object in the queue and print it on
  58. // the standard output
  59. Object obj = getO2AObject();
  60. if (obj != null) {
  61. System.out.println("Got an object from the queue: [" + obj + "]");
  62. } else
  63. block();
  64. }
  65.  
  66. });
  67. }
  68.  
  69. public void takeDown() {
  70. // Disables the object-to-Agent communication channel, thus
  71. // waking up all waiting threads
  72. setEnabledO2ACommunication(false, 0);
  73. }
  74.  
  75. } // End of CustomAgent class
  76.  
  77. public static void main(String args[]) {
  78.  
  79. try {
  80. Runtime rt = Runtime.instance();// 获取jade运行时
  81.  
  82. // Exit the JVM when there are no more containers around
  83. rt.setCloseVM(true);
  84.  
  85. // 看运行参数中是否有-container
  86. if (args.length > 0) {
  87. if (args[0].equalsIgnoreCase("-container")) {
  88. // 创建一个默认的profile
  89. Profile p = new ProfileImpl(false);
  90. // p.setParameter(Profile.MAIN, "false");
  91.  
  92. // Create a new non-main container, connecting to the default
  93. // main container (i.e. on this host, port 1099)
  94. System.out.println("Launching the Agent container ..." + p);
  95. AgentContainer ac = rt.createAgentContainer(p);
  96.  
  97. // 创建一个新的Agent
  98. AgentController dummy = ac.createNewAgent("inProcess",
  99. "jade.tools.DummyAgent.DummyAgent", new Object[0]);
  100.  
  101. // 启动它
  102. System.out.println("Starting up a DummyAgent...");
  103. dummy.start();
  104.  
  105. // 等10秒
  106. Thread.sleep(10000);
  107.  
  108. // 杀死这个Agent
  109. System.out.println("Killing DummyAgent...");
  110. dummy.kill();
  111.  
  112. // 在同一虚拟机上创建另一个容器,NB,
  113. // NB. 两个容器不能共享同一个 Profile对象!!! -->
  114. // 所以需再创建一个profile对象
  115. p = new ProfileImpl(false);
  116. // p.putProperty(Profile.MAIN, "false");
  117. AgentContainer another = rt.createAgentContainer(p);
  118.  
  119. // 用两个参数创建一个移动agnet
  120. Object[] arguments = new Object[2];
  121. arguments[0] = "Hello World!";
  122. arguments[1] = dummy;
  123. AgentController mobile = another.createNewAgent("Johnny",
  124. "examples.mobile.MobileAgent", arguments);
  125. mobile.start();
  126.  
  127. return;
  128. }
  129. }
  130.  
  131. // 在8888端口运行一个完整的平台t
  132. // create a default Profile
  133. Profile pMain = new ProfileImpl(null, 8888, null);
  134.  
  135. System.out.println("Launching a whole in-process platform..." + pMain);
  136. AgentContainer mc = rt.createMainContainer(pMain);
  137.  
  138. // 使用默认的profile启动一个容器
  139. ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
  140. System.out.println("Launching the Agent container ..." + pContainer);
  141. AgentContainer cont = rt.createAgentContainer(pContainer);
  142. System.out.println("Launching the Agent container after ..." + pContainer);
  143.  
  144. System.out.println("Launching the rma Agent on the main container ...");
  145. AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", new Object[0]);
  146. rma.start();
  147.  
  148. // Launch a custom Agent, taking an object via the
  149. // object-to-Agent communication channel. Notice how an Object
  150. // is passed to the Agent, to achieve a startup synchronization:
  151. // this Object is used as a POSIX 'condvar' or a Win32
  152. // 'EventSemaphore' object...
  153.  
  154. CondVar startUpLatch = new CondVar();
  155.  
  156. AgentController custom = mc.createNewAgent("customAgent", CustomAgent.class.getName(),
  157. new Object[] { startUpLatch });
  158. custom.start();
  159.  
  160. // Wait until the Agent starts up and notifies the Object
  161. try {
  162. startUpLatch.waitOn();
  163. } catch (InterruptedException ie) {
  164. ie.printStackTrace();
  165. }
  166.  
  167. // Put an object in the queue, asynchronously
  168. System.out.println("Inserting an object, asynchronously...");
  169. custom.putO2AObject("Message 1", AgentController.ASYNC);
  170. System.out.println("Inserted.");
  171.  
  172. // Put an object in the queue, synchronously
  173. System.out.println("Inserting an object, synchronously...");
  174. custom.putO2AObject(mc, AgentController.SYNC);
  175. System.out.println("Inserted.");
  176.  
  177. } catch (Exception e) {
  178. e.printStackTrace();
  179. }
  180.  
  181. }
  182.  
  183. }

现在看看servlet能不能调用这个,在Eclipse中建立一个web工程,添加jade库,建立一个servlet在servlet中进行调用Agent,看能不能输出结果。
其中主要文件如下

文件名:StartServlet.java:

  1. package examples;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午12:57:37
  7. */
  8.  
  9. import jade.core.Profile;
  10. import jade.core.ProfileImpl;
  11. import jade.core.Runtime;
  12. import jade.wrapper.AgentContainer;
  13. import jade.wrapper.AgentController;
  14.  
  15. import java.io.IOException;
  16. import java.io.PrintWriter;
  17.  
  18. import javax.servlet.ServletException;
  19. import javax.servlet.http.HttpServlet;
  20. import javax.servlet.http.HttpServletRequest;
  21. import javax.servlet.http.HttpServletResponse;
  22.  
  23. public class StartServlet extends HttpServlet {
  24.  
  25. protected void processRequest(HttpServletRequest request, HttpServletResponse response)
  26. throws ServletException, IOException {
  27. response.setContentType("text/html;charset=UTF-8");
  28. PrintWriter out = response.getWriter();
  29.  
  30. out.println("<html>");
  31. out.println("<head>");
  32. out.println("<title>Servlet StartServlet</title>");
  33. out.println("</head>");
  34. out.println("<body>");
  35. out.println("<h1>Servlet StartServlet at " + request.getContextPath() + "</h1>");
  36. out.println("<font size=10 >你好</font>");
  37. try {
  38. Runtime rt = Runtime.instance();
  39. rt.setCloseVM(true);
  40. Profile pMain = new ProfileImpl(null, 8888, null);
  41.  
  42. AgentContainer mc = rt.createMainContainer(pMain);
  43. // set now the default Profile to start a container
  44. ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
  45. out.println("运行Agent容器 ..." + pContainer);
  46. AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", null);
  47. rma.start();
  48. AgentController custom = mc.createNewAgent("custom", "examples.CustomAgent", null);
  49. custom.start();
  50.  
  51. out.println("我已经启动了一个小Agent");
  52.  
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56.  
  57. out.println("</body>");
  58. out.println("</html>");
  59.  
  60. out.close();
  61. }
  62.  
  63. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  64. throws ServletException, IOException {
  65. processRequest(request, response);
  66. }
  67.  
  68. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  69. throws ServletException, IOException {
  70. processRequest(request, response);
  71. }
  72.  
  73. public String getServletInfo() {
  74. return "Short description";
  75. }
  76. }

CustomAgent.java:

  1. package examples;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午1:03:40
  7. */
  8. import jade.core.Agent;
  9. import jade.core.behaviours.SimpleBehaviour;
  10.  
  11. public class CustomAgent extends Agent {
  12.  
  13. public void setup() {
  14. SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
  15. boolean finished = false;
  16.  
  17. public void action() {
  18. System.out.println("Hello World Behaviour run: 你好,世界!");
  19. System.out.println("-----我是:-----");
  20. System.out.println("我的本地名称是:" + getLocalName());
  21. System.out.println("我全局唯一的标志名称为:" + getName());
  22. finished = true;
  23. try {
  24. Thread.sleep(40000);
  25. } catch (java.lang.InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. System.out.println("已经过了40秒钟");
  29. // 这里是为了测试关掉IE之后控制台上还会不会输出信息。
  30. }
  31.  
  32. public boolean done() {
  33. return finished;
  34. }
  35.  
  36. };
  37. addBehaviour(helloBehaviour);
  38. }
  39.  
  40. }

web.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  3. <display-name>jade</display-name>
  4. <servlet>
  5. <servlet-name>StartServlet</servlet-name>
  6. <servlet-class>examples.StartServlet</servlet-class>
  7. </servlet>
  8. <servlet-mapping>
  9. <servlet-name>StartServlet</servlet-name>
  10. <url-pattern>/StartServlet</url-pattern>
  11. </servlet-mapping>
  12. <session-config>
  13. <session-timeout>
  14. 30
  15. </session-timeout>
  16. </session-config>
  17. <welcome-file-list>
  18. <welcome-file>index.html</welcome-file>
  19. <welcome-file>index.htm</welcome-file>
  20. <welcome-file>index.jsp</welcome-file>
  21. <welcome-file>default.html</welcome-file>
  22. <welcome-file>default.htm</welcome-file>
  23. <welcome-file>default.jsp</welcome-file>
  24. </welcome-file-list>
  25. </web-app>

在url:http://localhost:8888/jade/StartServlet中看到如下结果:
Servlet StartServlet at /jade

你好 运行Agent容器 ...(Profile main=true local-host=59.73.87.114 port=8888 services=jade.core.mobility.AgentMobilityService;jade.core.event.NotificationService host=59.73.87.114 local-port=8888 mtps=[jade.mtp.http.MessageTransportProtocol] jvm=j2se) 我已经启动了一个小Agent

在Tomcat控制台上输出信息:

Hello World Behaviour run: 你好,世界!

-----我是:-----

我的本地名称是:custom

我全局唯一的标志名称为:custom@deepin-84e2a07b:8888/JADE

已经过了40秒钟

同时图形化JADE容器运行,其中“已经过了40秒钟”是在浏览器关闭之后显示,说明Agent容器及Agent启动后一直运行着。

奇怪的是,我每次退出主容器,总显示

Exception while removing reference: java.lang.InterruptedException

java.lang.InterruptedException

at java.lang.Object.wait(Native Method)

at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)

at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)

at sun.java2d.Disposer.run(Disposer.java:107)

at java.lang.Thread.run(Thread.java:595)

AWT blocker activation interrupted: //后面这个是JADE GUI的bug么?

java.lang.InterruptedException

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:474)

at sun.awt.AWTAutoShutdown.activateBlockerThread(AWTAutoShutdown.java:309)

at sun.awt.AWTAutoShutdown.setToolkitBusy(AWTAutoShutdown.java:226)

at sun.awt.AWTAutoShutdown.notifyToolkitThreadBusy(AWTAutoShutdown.java:118)

at sun.awt.windows.WToolkit.eventLoop(Native Method)

at sun.awt.windows.WToolkit.run(WToolkit.java:269)

at java.lang.Thread.run(Thread.java:595)

不知道什么问题?

一个Agent如何以程序的方式生成另一个Agent:

可以通过以下方式进行创建:

  1. String name = "Alice" ;
  2. AgentContainer c = getContainerController();
  3. try {
  4. AgentController a = c.createNewAgent( name, "Pong", null );
  5. a.start();
  6. }
  7. catch (Exception e){}

其中,createNewAgent方法的第一个参数是要创建的Agent的名称,第二个是Agent的类名,实际使用时要包括他所在的命名空间(包名),第三个参数是要传入的参数的名称。
例子:

  1. package jadePrime.acl;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午1:08:17
  7. */
  8. /**
  9. * Program which creates another Agent and sends
  10. ------------ it some messages
  11. comm2.java
  12. *
  13. */
  14.  
  15. import jade.core.AID;
  16. import jade.core.Agent;
  17. import jade.core.behaviours.SimpleBehaviour;
  18. import jade.lang.acl.ACLMessage;
  19. import jade.wrapper.AgentContainer;
  20. import jade.wrapper.AgentController;
  21.  
  22. public class Comm2 extends Agent {
  23. String name = "Alice";
  24. AID alice = new AID(name, AID.ISLOCALNAME);
  25.  
  26. protected void setup() {
  27.  
  28. AgentContainer c = getContainerController();
  29. System.out.println("find container!");
  30.  
  31. try {
  32. AgentController a = c.createNewAgent(name, "jadePrime.acl.Pong", null);
  33. a.start();
  34. System.out.println("++++pong has created:" + alice);
  35.  
  36. } catch (Exception e) {
  37. System.out.println("Create Agent Error!");
  38. addBehaviour(new SimpleBehaviour(this) {
  39. int n = 0;
  40.  
  41. public void action() {
  42. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  43. msg.setContent("Message #" + n);
  44. msg.addReceiver(alice);
  45. System.out.println("+++ Sending: " + n);
  46. send(msg);
  47. block(1000);
  48. }
  49.  
  50. public boolean done() {
  51. return ++n > 3;
  52. }
  53. });
  54. }
  55.  
  56. }
  57. }

当我们创建一个Comm2的Agent时,在控制台上会打印出创建alice成功的消息。
如何收集当前AMS中Agent列表

  1. package jadePrime.manage;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午1:09:53
  7. */
  8.  
  9. import jade.core.AID;
  10. import jade.core.Agent;
  11. import jade.domain.AMSService;
  12. import jade.domain.FIPAAgentManagement.AMSAgentDescription;
  13. import jade.domain.FIPAAgentManagement.SearchConstraints;
  14.  
  15. public class AMSDump extends Agent {
  16. protected void setup() {
  17. AMSAgentDescription[] Agents = null;
  18. try {
  19. SearchConstraints c = new SearchConstraints();
  20. c.setMaxResults(new Long(-1));
  21. Agents = AMSService.search(this, new AMSAgentDescription(), c);
  22. } catch (Exception e) {
  23. System.out.println("Problem searching AMS: " + e);
  24. e.printStackTrace();
  25. }
  26.  
  27. AID myID = getAID();
  28. for (int i = 0; i < Agents.length; i++) {
  29. AID AgentID = Agents[i].getName();
  30. System.out.println((AgentID.equals(myID) ? "*** " : " ") + i + ": "
  31. + AgentID.getName());
  32. }
  33. doDelete();
  34. // System.exit(0);
  35. }
  36.  
  37. }// end class AMSDump

详见:http://www.iro.umontreal.ca/%7Evaucher/Agents/JADE/primer4.html#5

JADE中如何使用DF(Directory Facilitator)Agent提供的黄页服务。
这个比较好理解,DF相当于一个目录服务器,每个提供服务的Agent可以向DF注册其服务,然后,其他的Agent可以从DF中查询该类服务,也可以订阅这类服务,如果是后者,那么一旦这类服务被注册到DF中,则订阅方就可以收到。例程如下:

文件一, DFRegisterAgent.java 服务提供方

  1. package yellowpages;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午1:11:14
  7. */
  8.  
  9. import jade.core.Agent;
  10. import jade.domain.DFService;
  11. import jade.domain.FIPAException;
  12. import jade.domain.FIPANames;
  13. import jade.domain.FIPAAgentManagement.DFAgentDescription;
  14. import jade.domain.FIPAAgentManagement.Property;
  15. import jade.domain.FIPAAgentManagement.ServiceDescription;
  16.  
  17. public class DFRegisterAgent extends Agent {
  18.  
  19. protected void setup() {
  20. String serviceName = "unknown";
  21.  
  22. // 从命令行的参数中读取服务的名称,默认为unknown
  23. Object[] args = getArguments();
  24. if (args != null && args.length > 0) {
  25. serviceName = (String) args[0];
  26. }
  27.  
  28. // 注册服务
  29. System.out.println("Agent " + getLocalName() + " registering service \"" + serviceName
  30. + "\" of type \"weather-forecast\"");
  31. try {
  32. // 必要的几个步骤
  33. DFAgentDescription dfd = new DFAgentDescription();
  34. dfd.setName(getAID());
  35. ServiceDescription sd = new ServiceDescription();
  36. sd.setName(serviceName);
  37. sd.setType("weather-forecast");// 设置服务类型为天气预报
  38. sd.addOntologies("weather-forecast-ontology");
  39. sd.addLanguages(FIPANames.ContentLanguage.FIPA_SL);
  40. // 使用服务的一方必须遵循的规范,和具有的本体知识
  41. sd.addProperties(new Property("country", "Italy"));
  42. dfd.addServices(sd);
  43.  
  44. DFService.register(this, dfd);
  45. } catch (FIPAException fe) {
  46. fe.printStackTrace();
  47. }
  48. }
  49. }

文件二.
DFSubscribeAgent.java订阅方

  1. package yellowpages;
  2.  
  3. /**
  4. * @function
  5. * @author Jacksile E-mail:tufujietec@foxmail.com
  6. * @date 2016年1月15日 下午1:12:26
  7. */
  8. import jade.core.AID;
  9. import jade.core.Agent;
  10. import jade.domain.DFService;
  11. import jade.domain.FIPAException;
  12. import jade.domain.FIPAAgentManagement.DFAgentDescription;
  13. import jade.domain.FIPAAgentManagement.Property;
  14. import jade.domain.FIPAAgentManagement.SearchConstraints;
  15. import jade.domain.FIPAAgentManagement.ServiceDescription;
  16. import jade.lang.acl.ACLMessage;
  17. import jade.proto.SubscriptionInitiator;
  18. import jade.util.leap.Iterator;
  19.  
  20. public class DFSubscribeAgent extends Agent {
  21.  
  22. protected void setup() {
  23. // Build the description used as template for the subscription
  24. DFAgentDescription template = new DFAgentDescription();
  25. ServiceDescription templateSd = new ServiceDescription();
  26. templateSd.setType("weather-forecast");
  27. templateSd.addProperties(new Property("country", "Italy"));
  28. template.addServices(templateSd);
  29.  
  30. SearchConstraints sc = new SearchConstraints();
  31. // 最多能接受10个结果
  32. sc.setMaxResults(new Long(10));
  33.  
  34. addBehaviour(new SubscriptionInitiator(this, DFService.createSubscriptionMessage(this,
  35. getDefaultDF(), template, sc)) {
  36. protected void handleInform(ACLMessage inform) {
  37. System.out.println("Agent " + getLocalName() + ": Notification received from DF");
  38. try {
  39. DFAgentDescription[] results = DFService
  40. .decodeNotification(inform.getContent());
  41. if (results.length > 0) {
  42. for (int i = 0; i < results.length; ++i) {
  43. DFAgentDescription dfd = results[i];
  44. AID provider = dfd.getName();
  45. // 同一个Agent可能提供很多服务,我们只对天气预报感兴趣
  46. Iterator it = dfd.getAllServices();
  47. while (it.hasNext()) {
  48. ServiceDescription sd = (ServiceDescription) it.next();
  49. if (sd.getType().equals("weather-forecast")) {
  50. System.out.println("Weather-forecast service for Italy found:");
  51. System.out.println("- Service \"" + sd.getName()
  52. + "\" provided by Agent " + provider.getName());
  53. }
  54. }
  55. }
  56. }
  57. System.out.println();
  58. } catch (FIPAException fe) {
  59. fe.printStackTrace();
  60. }
  61. }
  62. });
  63. }
  64. }

这样,编译后,我们为了体现发布服务和订阅服务时间上的一致关系,我们从命令行来运行这些类。假设已编译成功,文件标志在某目录下yellowpages\ DFSubscribeAgent.class 和yellowpages\ DFRegisterAgent.class,我们在yellowpages目录下运行命令
java jade.Boot –gui service1: yellowpages.DFRegisterAgent

系统运行主容器,同时控制台上显示Agent service1 registering service “noname” of type "weather-forecast"

然后我们在图形界面下,start new Agent,AgentName:subscriber ClassName:yellowpages.DFSubscribeAgent 添加后,控制台上会显示相关启动后的信息,但不会显示收到服务的消息。然后再start new Agent,AgentName:service2 ClassName:yellowpages.DFRegisterAgent 参数设为:rainny,这是控制台上显示注册服务成功的消息和订阅到服务的消息。显示如下:

JADE中使用本体:

    Agent之间进行通信要有相同的语言,词汇和协议。在JADE中,Agents之间通信的方式可以有三种:1.使用字符串表达信息的内容,是最基本的方式.当消息内容是原子数据时,这种方式非常便利.2.消息内容使用序列化的java对象,对本地应用,特别是所有Agent都用java实现的情况下也是很有用的.3.为了jade能够以FIPA格式队消息进行编码和解码,扩展预先定义好的类,亦即使用本体的方式。这种方式允许jade的Agent可以同其他异质Agent系统进行互操作。这三种方式下对应设置和获取内容的方法对应如下:

现在有一些已经存在的language来描述ontologies,如DAML+OIL和OWL,JADE并不直接支持这些ontologies,而是将ontologies编码为java类(比如protégé可以将本体直接导出为java类)。

本体提供了Agent交互的语义支持,但必须与内容语言结合使用,后者是Agent交互的语法支持。JADE支持的三种内容语言包括:FIPA-SL类似lisp的语言族;Leap-encoding应用于嵌入式开发;JavaCodec,JADE特定的内容语言。

JADE提升篇的更多相关文章

  1. C# 程序性能提升篇-1、装箱和拆箱,枚举的ToString浅析

    前景提要: 编写程序时,也许你不经意间,就不知不觉的使程序代码,发生了装箱和拆箱,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候,减少装箱和拆 ...

  2. C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析

    前景提要: 编写程序时,也许你不经意间,就不知不觉的定义了错误的类型,从而发生了额外的性能消耗,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候 ...

  3. Java提升篇之反射的原理(二)

    Java提升篇之通过反射越过泛型检查 /* *问题:在一个ArrayList<Integer>对象中,在这个集合中添加一个字符串. */ 在我们还没有学反射前,遇到这个问题都是无法实现的, ...

  4. Java提升篇之反射的原理

    Java提升篇之反射的原理 1.构造方法的反射 import java.lang.reflect.Constructor; public class ReflectConstructor { publ ...

  5. 大数据系列博客之 --- 深入简出 Shell 脚本语言(提升篇)

    首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...

  6. 嵌入式LInux之C语言提升篇---Skr Skr Up Up

    嵌入式C语言提升 致敬:每一个奋斗的人! Up Up UpC语言常见编译错误1.预处理错误 -E    1-1 找不到源文件错误         自己定义头文件 使用 “xxx.h” 搜索的目录 ./ ...

  7. [Android 性能优化系列]内存之提升篇--应用应该怎样管理内存

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...

  8. Android提升篇系列:Activity recreate(Activity 重新创建/自我恢复)机制(一)

    注:本文中的recreate是指当内存不足时,Activity被回收,但再次来到此Activity时,系统重新恢复的过程.例如:当Activity A到Activity B时,如果内存不足,A被回收, ...

  9. mysql技能提升篇 - Sqlyog高级应用

    mysql作为绝大部分公司使用的数据库,自然是牛牛牛! 每个人都能设计数据库,都能从删库到跑路.但是,如何做到更好,更快,更准地建立你的mysql数据库,这是个值得关注的问题(尽管很多人已经去搞大数据 ...

随机推荐

  1. CURL模拟登陆

    index.html <a href="http://adtuu-server.com/login/login.php?auth_username=admin&auth_pas ...

  2. 【原创】一起学C++ 之->(箭头符号) ---------C++ primer plus(第6版)

    1.C++新手在指定结构成员时,不知道何时用.运算符,何时是用->运算符. 结论:如果结构标识符是结构名,则使用句点运算符:如果标识符是指向结构的指针,则使用箭头运算符. #include &l ...

  3. PowerDesigner 非数值默认值时会自动增加单引单

    在PowerDesigner中,如果默认值是非数值型的,那么 PowerDesigner 会默认加上单引号 因此我们需要把这个默认的单引号干掉,如果是需要设置字符串默认值的时候,就手工加上 单引号 即 ...

  4. Cube and EarthDistance

    前言:项目中用到了postgreSQL中的earthdistance()函数功能计算地球上两点之间的距离,中文的资料太少了,我找到了一篇英文的.讲的很好的文章 ,特此翻译,希望能够帮助到以后用到ear ...

  5. EXTJS 资料 combo 点一次触发一次

    { xtype: 'combo', id: 'ApplyToModel', name: 'ApplyToModel', store: comStoreApplyToModel, valueField: ...

  6. aaaa

    http://www.host.com http://www.host.com http://sz.weixun.com/scenery/details-3.htm http://sz.weixun. ...

  7. 【tyvj1860】后缀数组

    描述 我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串.后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])< ...

  8. Understanding Responsive Web Design: Cross-browser Compatibility

    http://www.sitepoint.com/understanding-responsive-web-design-cross-browser-compatibility/ In the las ...

  9. dijkstra,bellman-ford,floyd分析比较

    http://www.cnblogs.com/mengxm-lincf/archive/2012/02/11/2346288.html 其实我一直存在疑惑是什么导致dijkstra不能处理负权图? 今 ...

  10. Debugging with GDB 用GDB调试多线程程序

    Debugging with GDB http://www.delorie.com/gnu/docs/gdb/gdb_25.html GDB调试多线程程序总结 一直对GDB多线程调试接触不多,最近因为 ...