本以为The ONE会每隔updateInterval
将TTL(time-to-live)到期的包丢弃,其实不是这样的,而是每隔1分钟丢弃TTL到期的包。本文介绍消息生存时间TTL以及因TTL到期丢包的技术细节,包括dropExpiredMessages
, deleteMessage
。
1. TTL
1.1 单位
消息生存时间TTL默认单位是分,可以通过设置文件将其改其秒,相关源代码如下:
//Message.java
/*** TTL单位默认是分 ***/
public static final String TTL_SECONDS_S = "Scenario.ttlSeconds";
private static boolean ttlAsSeconds = false; //TTL单位默认为分
public static final int INFINITE_TTL = -1; //Value for infinite TTL of message
public static void reset() {
ttlAsSeconds = s.getBoolean(TTL_SECONDS_S, false); //Scenario.ttlSeconds
}
//可以在设置文件设置消息生成时间TTL,如下:
# Message TTL of 300 minutes (5 hours)
Group.msgTtl = 300
1.2 默认值
如果在设置文件不设置Group.msgTtl
和Scenario.ttlSeconds
,消息生存时间TTL默认值是infinite
,确切的说是Integer.MAX_VALUE
。相关源代码如下:
/*** 新创建消息的TTL为-1,即消息的TTL为Integer.MAX_VALUE ***/
//Message.java
public static final int INFINITE_TTL = -1;
public Message(DTNHost from, DTNHost to, String id, int size) {
this.initTtl = INFINITE_TTL;
}
/*** 创建消息,若设置文件没设置Group.msgTtl,则按INFINITE_TTL来 ***/
//MessageRouter.java
public boolean createNewMessage(Message m) {
m.setTtl(this.msgTtl);
m.addToMessages(true); //将消息加入到HashMap<String, Message> messages
return true;
}
//MessageRouter.java,从设置文件读取Group.msgTtl
public MessageRouter(Settings s) {
this.msgTtl = Message.INFINITE_TTL; //即msgTtl为-1
if (s.contains(MSG_TTL_S)) { //public static final String MSG_TTL_S = "msgTtl";
this.msgTtl = s.getInt(MSG_TTL_S);
}
}
initTtl
标识着该消息的生存时间是无限的,即一直存在于仿真期间。但当取得该消息的TTL时,返回的是Integer.MAX_VALUE
,源代码如下:
public int getTtl() {
if (this.initTtl == INFINITE_TTL) { //默认的情况,没设置Group.msgTtl和Scenario.ttlSeconds
return Integer.MAX_VALUE;
} else {
if (ttlAsSeconds) { //TTL单位是秒,通过Scenario.ttlSeconds=true设置
return (int)(this.initTtl - (SimClock.getTime()-this.timeCreated) );
} else { //TTL单位是分
return (int)( ((this.initTtl * 60) - (SimClock.getTime()-this.timeCreated)) /60.0 );
}
}
}
2. 丢包drop
2.1 何时丢包
The ONE丢包有两种情况:其一,TTL到期;其二,缓冲区满了。这点只考虑TTL到期丢包的情况。最开始,以为每个updateInterval
都会将那些TTL到期的包丢弃,看了源代码才发现,其实不是这样的,而是1分钟或60秒。相关源代码如下:
//ActiveRouter.java
public void update() {
...
/*** 丢弃那些TTL到期的数据包(每隔ttlCheckInterval检查一次) ***/
if (SimClock.getTime() - lastTtlCheck >= ttlCheckInterval && sendingConnections.size() == 0) {
dropExpiredMessages();
lastTtlCheck = SimClock.getTime();
}
...
}
//关于ttlCheckInterval
private static int ttlCheckInterval = 60;
public ActiveRouter(Settings s) {
...
ttlCheckInterval = (new Settings().getBoolean(Message.TTL_SECONDS_S, false) ? 1 : 60);
}
值得注意的是:只有在节点没有发送数据的时候(sendingConnections
的size为0),才会丢包。简单防止正在传输的消息被删除。
2.2 dropExpiredMessages
dropExpiredMessages删除TTL到期的消息,源代码如下:
//ActiveRouter.java
protected void dropExpiredMessages() {
Message[] messages = getMessageCollection().toArray(new Message[0]);
for (int i=0; i<messages.length; i++) {
int ttl = messages[i].getTtl();
if (ttl <= 0) {
deleteMessage(messages[i].getId(), true); //deleteMessage(String id, boolean drop)
}
}
}
2.3 deleteMessage
deleteMessage
从消息缓冲区删除指定消息,并更多相关reports
,源代码如下:
//MessageRouter.java
public void deleteMessage(String id, boolean drop) {
Message removed = removeFromMessages(id);
if (removed == null) throw new SimError("no message for id " + id + " to remove at " + this.host);
for (MessageListener ml : this.mListeners) { //消息监听器通知更新reports相关内容
ml.messageDeleted(removed, this.host, drop);
}
}