本以为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.msgTtlScenario.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);
    }
}
本文系Spark & Shine原创,转载需注明出处本文最近一次修改时间 2022-03-27 10:28

results matching ""

    No results matching ""