JADE学习笔记4:Agent通信
来源:互联网 发布:c语言猜数游戏 编辑:程序博客网 时间:2024/06/05 10:59
Agent通信是JADE中最基本的功能,基于异步消息传递。每个Agent都有一个“邮箱”(Agent消息队列),JADE实时运行环境传递Agent发送的消息传递到邮箱内,通知接收Agent。Agent是否处理队列中的消息由Agent开发者决定。
消息格式遵循FIPA-ACL消息结构,每条消息包括以下几个内容:
1)sender:消息的发送者,用Agent标志AID表示。
2)receivers:接受Agent消息的Agent,可以是多个。
3)Reply-to:应收到回应的接受者。
4)Performative:通信行为或称通信原语,标志发送消息的目的,即发送者想要通过发送消息干什么。通常有这样一些常值:REQUEST,INFORM,ACCEPT_PROPOSAL,REJECT_PROPOSAL,PROPOSE等。如REQUEST表示发送者希望接收者执行一个特定的任务,INFORM表示发送者希望接收者了解一些事情,PROPOSE或者CFP(Call For Proposals)表示发送者希望进行一次谈判。
5)Content:消息的内容。
6)Language:内容语言,比如内容的编码格式。
7)ontology:双方都能够理解的消息内容的概念说明和语义描述。
发送消息时调用send()方法,接收消息调用Receive()方法。
简单实例:
发送者:l_3_ACL_cyc文件夹中建立类文件Sender
package l_3_ACL_cyc;import jade.core.AID;import jade.core.Agent;import jade.core.behaviours.*;import jade.lang.acl.ACLMessage;public class Sender extends Agent{ public void setup() { addBehaviour(new Behaviour() { private boolean finished = false; @Override public void action() { // TODO 自动生成的方法存根 doWait(5000); ACLMessage acl=new ACLMessage(ACLMessage.INFORM); //通知 AID r=new AID(); r.setLocalName("Rec"); //设置接收Agent的本地名 acl.addReceiver(r); //添加到ACL消息中 acl.setSender(getAID()); //设置发送者本地名,这里可以省略 acl.setContent("Hello,Rec"); //设置内容 send(acl); //向Rec发送消息 System.out.println("local name is:" + getLocalName()); System.out.println(getLocalName()+" send Hello to Rec"); System.out.println("the content is : "+acl.getContent()); System.out.println("send finished"); doWait(5000); finished=true; doDelete(); } @Override public boolean done() { // TODO 自动生成的方法存根 return finished; } }); }}
接收者:l_3_ACL_cyc文件夹中创建类文件Receiver
package l_3_ACL_cyc;import jade.core.*;import jade.core.behaviours.*;import jade.lang.acl.ACLMessage;public class Receiver extends Agent { public void setup() { addBehaviour(new CyclicBehaviour() { @Override public void action() { // TODO 自动生成的方法存根 ACLMessage acl1=receive(); if(acl1!=null) { System.out.println("receiving"); doWait(2000); System.out.println(getLocalName()+" receive a message"); System.out.println("the message is: "+acl1.getContent()); System.out.println("the message is: "+acl1.getSender().getLocalName()); doDelete(); } }}); }}
运行时,通过-gui命令调出GUI管理器。start new Agent,先启动Receiver类,命名为Rec(必须与前面添加接收者时的命名保持一致);
再启动Sender类。
运行结果:
local name is:SendSend send Hello to Recthe content is : Hello,Recsend finishedreceivingRec receive a messagethe message is: Hello,Recthe message is from: Send
这里,ACLMessage接收消息是通过一个循环行为实现的,这样会占用较长CPU时间。我们也可以不用循环行为,通过block()方法,它的作用是阻塞行为,使Agent不再运行此行为。当新消息插入到消息队列中时,阻塞的行为被激活,再次执行处理接收的消息。
其代码如下,Sender类的建立方法与上述一样。
public class Receiver extends Agent{ public void setup() { Behaviour b=new SimpleBehaviour() { boolean finished=false; @Override public void action() { // TODO 自动生成的方法存根 ACLMessage acl1=receive(); if(acl1!=null) { System.out.println("receiving"); doWait(2000); System.out.println(getLocalName()+" receive a message"); System.out.println("the message is: "+acl1.getContent()); System.out.println("the message is: "+acl1.getSender().getLocalName()); finished = true; myAgent.doDelete(); } else { System.out.println(getLocalName()+" does not receive a message"); block();//如果没有消息,则阻塞行为 } } @Override public boolean done() { // TODO 自动生成的方法存根 return finished; }}; addBehaviour(b); }}
接收者的代码流程为:添加一个简单行为,这一行为检查现在是否有受到消息,若没有,则执行block()方法组织目前的behaviour执行,直到有新的消息到达。
上述只是实现了消息的传递,我们往往希望能完成信息的交互。FIPA定义了一组交互协议,在jade.proto包中提供了多种常用交互协议的支持。
下面是一个稍复杂的基于交互协议的例子。Baz作为行为发起人,向Bob发出结婚请求,Bob接到信息后,回复,然后Baz接到回复并输出信息。
l_5_ACL_complex文件夹中建立类文件Name_Baz
package l_5_ACL_complex;import jade.core.AID;import jade.core.Agent;import jade.domain.FIPANames.InteractionProtocol;import jade.lang.acl.ACLMessage;import jade.proto.SimpleAchieveREInitiator;public class Name_Baz extends Agent { static class MarriageProposer extends SimpleAchieveREInitiator{ protected MarriageProposer(Agent Agent, ACLMessage msg) { super(Agent, msg); } //对Bob的回复做出响应 protected void handleAgree(ACLMessage msg) { //Bob回复通信,输出函数 System.out.println(myAgent.getLocalName() + " said excitedly : " + msg.getSender().getLocalName() + "has agreed to marry me !"); } protected void handleRefuse(ACLMessage msg) {//Bob回复拒绝,输出函数 System.out.println(myAgent.getLocalName() + " said sadly : Oh no! " + msg.getSender().getLocalName() + " refused me ."); } protected void handleInform(ACLMessage msg) {//Bob回复一段话,输出函数 System.out.println(myAgent.getLocalName() + " said :" + msg.getSender().getLocalName()+ " has informed me of the status of my request." + "They said : "+ msg.getContent()); } protected void handleNotUnderstood(ACLMessage msg) {//Bob回复不理解请求,Baz输出 System.out.println(myAgent.getLocalName() + " said :" + msg.getSender().getLocalName() + " has indicated that they didn't understand."); } protected void handleOutOfSequence(ACLMessage msg) { //Bob给了一个有误的回复 System.out.println(myAgent.getLocalName() + " said :" + msg.getSender().getLocalName() + "gave me an unexcepted answer"); } } public void setup() { System.out.println(getLocalName() + ": about to propose marriage to Bob "); doWait(3000); // wait for bob to be started. ACLMessage msg = new ACLMessage(ACLMessage.REQUEST); AID to = new AID(); to.setLocalName("Bob"); msg.setSender(getAID()); msg.addReceiver(to); msg.setContent("Marry me!"); msg.setProtocol(InteractionProtocol.FIPA_REQUEST); addBehaviour(new MarriageProposer(this, msg)); }}
l_5_ACL_complex文件夹中建立类文件Name_Bob
package l_5_ACL_complex;import jade.core.*;import jade.domain.FIPANames.InteractionProtocol;import jade.domain.introspection.AddedBehaviour;import jade.lang.acl.ACLMessage;import jade.lang.acl.MessageTemplate;import jade.proto.SimpleAchieveREInitiator;import jade.proto.SimpleAchieveREResponder;public class Name_Bob extends Agent{ static class MarriageResponder extends SimpleAchieveREResponder{ //准备答复 public MarriageResponder(Agent a) { super(a, createMessageTemplate (InteractionProtocol.FIPA_REQUEST)); // TODO 自动生成的构造函数存根 } private static final long serialVersionUID = 1L; protected ACLMessage prepareResponse(ACLMessage msg) { ACLMessage responder=msg.createReply() ; if(msg.getContent()!=null&&msg.getContent().equals("Marry me!")) { System.out.println(myAgent.getLocalName()+": "+ msg.getSender().getLocalName()+" has asked me to marry him"); AID r=msg.getSender(); if(r.getLocalName().equals("Baz")) { responder.setPerformative(ACLMessage.AGREE); System.out.println(myAgent.getLocalName()+": I am going to agree."); } else { responder.setPerformative(ACLMessage.REFUSE); System.out.println(myAgent.getLocalName()+": I am going to turn him down."); } } else { responder.setPerformative(ACLMessage.NOT_UNDERSTOOD); System.out.println("I did not understand what "+msg.getSender().getLocalName()+" said"); } return responder; } protected ACLMessage prepareResultNotification (ACLMessage inmsg,ACLMessage outmsg) { //最终答复 ACLMessage msg=inmsg.createReply(); msg.setPerformative(ACLMessage.INFORM); msg.setContent("I do!"); return msg; } } protected void setup() { System.out.println(getLocalName()+" : I wonder if anybody would like to marry me!"); addBehaviour(new MarriageResponder(this)); }}
按照以前记载,先打开GUI管理器,GUI管理打开之后先建立一个名为Bob的Agent,对应的类为l_5_ACL_complex.Name_Bob,然后再建立一个名为baz的Agent,对应的类为l_5_ACL_complex.Name_Baz,顺序不能变,以下是输出结果:
Bob : I wonder if anybody would like to marry me!Baz: about to propose marriage to Bob Bob: Baz has asked me to marry himBob: I am going to agree.Baz said excitedly : Bobhas agreed to marry me !Baz said :Bob has informed me of the status of my request.They said : I do!
- JADE学习笔记4:Agent通信
- JADE学习笔记3:Agent行为
- JADE学习笔记之四,外部程序调用agent
- JADE学习笔记2 :Agent的创建和运行
- jade学习笔记一
- jade 学习笔记二
- jade template 学习笔记
- Jade学习笔记
- node jade学习笔记
- Jade学习笔记
- jade 学习笔记
- jade中的agent behaviour
- Jade Agent 交互协议
- JADE学习笔记1:JADE简介与配置
- JADE平台学习笔记(二)
- JADE学习笔记之三:行为
- node模版引擎Jade学习笔记
- 模板引擎——Jade学习笔记
- mac安装ns3仿真平台
- 进程同步(操作系统)
- JSON.parse()和JSON.stringify()
- Java多线程系列(五)—LockSupport源码分析
- RPI.GPIO使用手册
- JADE学习笔记4:Agent通信
- 深度学习网络模型可视化
- html无法显示中文名图片,改为英文就可以显示,解决方案
- 论文实践学习
- 什么是频谱
- Jmeter连接MySql
- 【入门教程】SequoiaDB+Postgresql数据实时检索最佳实践
- Window 浏览器窗口对象
- bzoj 1922: [Sdoi2010]大陆争霸