可以使用The ONE的消息事件产生器MessageEventGenerator
自动创建消息,本文深入源码介绍用MessageEventGenerator
创建消息的过程。
1. MessageEventGenerator
1.1 设置文件
可以用The ONE的MessageEventGenerator
产生消息事件,进而自动创建消息,在my_settings.txt
设置如下:
# my_settings.txt Events2.class = MessageEventGenerator Events2.interval = 25,35 Events2.size = 5k,10k Events2.hosts = 0, 79 Events2.tohosts = ... Events2.prefix = M
值得注意的是,hosts
和tohosts
包括下界但不包括上界,即[0, 79)
;size
和interval
上下界都不包括,即(min, max)
,详情见MessageEventGenerator.java
。
1.2 加入事件队列
The ONE初始化时,会创建EventQueueHandler
的一个实例,用于管理The ONE所有事件,详情可参考博文《The ONE使用笔记:宏观角度理解事件是如何组织》。MessageEventGenerator
事件就是在EventQueueHandler
构造函数中被加入到事件队列的。相关源代码如下:
//EventQueueHandler.java public EventQueueHandler() { ... //消息产生器事件 else if (s.contains(CLASS_SETTING)) { String className = CLASS_PACKAGE + "." + s.getSetting(CLASS_SETTING); //即input.MessageEventGenerator EventQueue eq = (EventQueue)s.createIntializedObject(className); queues.add(eq); //加入到事件队列 } ... }
1.3 消息Message
描述一个消息Message
的属性有:id
,从哪里来到哪里去,创建和接收时间,TTL,大小等。Message
的主要成员变量如下:
//Message.java //identify private String id; private int uniqueId; //Unique ID of this message private String appID; //Application ID of the application that created the message //about DTNHost private DTNHost from; private DTNHost to; private List<DTNHost> path; //消息经过的路径 private int size; //bytes private int initTtl; private double timeReceived; private double timeCreated; private int responseSize; private Message requestMsg;
2 消息创建
消息创建分两步:首先,由MessageEventGenerator.nextEvent()
产生一个消息创建事件MessageCreateEvent
;而后,当轮到处理MessageCreateEvent
时,才真正创建一个消息。
2.1 消息创建事件
轮到处理MessageEventGenerator
事件时,调用其nextEvent
创建一个消息产生事件(只是一个事件,还不是消息)。更确切的说,World.update
的this.nextEventQueue.nextEvent
得到一个消息创建的外部事件。相关源代码如下:
//MessageEventGenerator.java public ExternalEvent nextEvent() { /* 从某个范围(在settings文件设置)随机选择消息的source, sink, size, interval */ from = drawHostAddress(this.hostRange); to = drawToAddress(hostRange, from); msgSize = drawMessageSize(); interval = drawNextEventTimeDiff(); //再过interval,再产生一个新的消息 /* 产生消息创建事件MessageCreateEvent */ MessageCreateEvent mce = new MessageCreateEvent(from, to, this.getID(), msgSize, responseSize, this.nextEventsTime); return mce; } //MessageCreateEvent.java public MessageCreateEvent(int from, int to, String id, int size, int responseSize, double time) { super(from,to, id, time); this.size = size; this.responseSize = responseSize; }
由此可见,MessageEventGenerator
实际上是产生一系列消息创建事件,正如其名。
2.2 创建消息
首先,需要获取消息创建事件,每隔updateInterval
,World.java
中的update()
会逐一处理事件。相关源代码如下:
//World.java中的update() public void update () { ...... setNextEventQueue(); //找到一个事件队列,该事件队列含有本updateInterval可以处理的事件 while (this.nextQueueEventTime <= runUntil) { simClock.setTime(this.nextQueueEventTime); ExternalEvent ee = this.nextEventQueue.nextEvent(); //取得事件 ee.processEvent(this); //处理事件 updateHosts(); //update all hosts after every event setNextEventQueue(); } ...... }
从上述代码可见,取得一个事件队列(setNextEventQueue
,可能是EventQueue
类型的MessageEventGenerator
),紧接着处理之processEvent
。processEvent()
在这里对应于MessageCreateEvent
的processEvent
函数,旨在创建消息。相关源代码如下:
//MessageCreateEvent.java public void processEvent(World world) { DTNHost to = world.getNodeByAddress(this.toAddr); DTNHost from = world.getNodeByAddress(this.fromAddr); Message m = new Message(from, to, this.id, this.size); m.setResponseSize(this.responseSize); from.createNewMessage(m); //创建消息 } //DTNHost.java DTNHost.createNewMessage --> MessageRouter.createNewMessage //MessageRouter.java public boolean createNewMessage(Message m) { m.setTtl(this.msgTtl); m.addToMessages( true); //将消息加入到HashMap<String, Message> messages return true; }
至此,一个消息创建完毕。值得注意的是,当一个新消息被创建时,会触发消息监听器MessageListener
,MessageListener
是一个接口,实现该接口主要是一些reports。通俗理解就是消息被创建后,通知相关reports更新统计信息(如CreatedMessagesReport
, MessageStatsReport
)。相关源代码如下:(详情可参考博文《The ONE使用笔记:深入源码理解消息监听器MessageListener》)
//MessageRouter.java protected void addToMessages(Message m, boolean newMessage) { this.messages.put(m.getId(), m); if (newMessage) { for (MessageListener ml : this.mListeners) { //触发消息监听器 ml.newMessage(m); } } }赞赏
微信赞赏
支付宝赞赏
Spark 您好!我是想问当目的社区内的节点收到了消息,第一个收到消息的节点将以广播的方式发送一个反馈消息给在通讯范围内的非本社区内节点,我就是搞不懂这个反馈消息应该怎么创建和转发。能像被传递的消息那样创建和转发吗?能不能给我一点提示和思路。谢谢您的多次回复。
没产生过EnergyLevelReport,抱歉不懂。
请问下您提到的 ExternalEvent ee = this.nextEventQueue.nextEvent(); //取得事件world.java的update()中,可以触发产生消息的事件,那么消息产生是按什么频率产生的哪?另外this.nextEventQueue.nextEvent()也会触发StandardEventsReader里的事件读取连接事件(比如infocom5里的),这里world里的this.nextEventQueue.nextEvent();是如何区别是读消息产生事件还是连接事件哪?
消息产生的频率是由设置文件Events.interval决定的。
至于如何区别连接和消息事件,这篇博文也许会有帮助。
The ONE使用笔记:宏观角度理解事件是如何组织
http://sparkandshine.net/the-one-use-notes-understand-how-organize-events-from-macro-perspectives/
您好,我想问一下,怎样设置,让源节点只产生一个事件
一种可行的方法是将消息作为外部事件输入,事件格式如下:
#time C message from to size
285.7 C M1 163 509 550704
558.6 C M2 752 241 100161
详情可以参考这里,The ONE使用笔记:仿真前向网络注入数据包,http://sparkandshine.net/the-one-use-notes-inject-packets-into-network-before-simulation/
好的,谢谢你
Pingback: The ONE使用笔记:创建自已的消息事件产生器 | Spark & Shine
Pingback: The ONE使用笔记:深入源码理解消息接收过程 | Spark & Shine
Pingback: The ONE使用笔记:深入源码理解消息转发过程 | Spark & Shine
Pingback: The ONE使用笔记:深入源码理解消息发送过程 | Spark & Shine
Pingback: The ONE使用笔记:消息发送与接收 | Spark & Shine
Pingback: The ONE使用笔记:目录 | Spark & Shine