THE ONE使用笔记(3)——DirectDelivery源码分析

1.DirectDelivery源码分析

DirectDelivery路由策略很简单,每个节点携带自创建的消息,不断移动,直到遇到目的节点,才把消息传递出去,整个通信过程从不借助其他节点。这点方法优点很明显,开销是最低的,但缺点也很明显,效率是最低的。作为路由的一种极端,通常作为benchmark与其他协议进行比较。

1.1 super.update

DirectDeliveryRouter的继承关系是这样的:DirectDeliveryRouter —> ActiveRouter –> MessageRouter。update都会被重写并调用上一层的update。

1.2 MessageRouter.update

相当于应用于的update,取决于具体应用,类似乎于事件处理函数取决于具体事件,其源代码如下:

//MessageRouter.java

public void update() {

for (Collection<Application> apps : this.applications.values()) { //update the status of transfer(s) on every simulation interval

    for (Application app : apps) {

            app.update(this.host);

        }

    }

}

1.3 ActiveRouter.update

ActiveRouter.update主要做4件事,其源代码如下:

//ActiveRouter.java

public void update() {

    super.update(); //调用MessageRouterupdate()

 

    /* in theory we can have multiple sending connections even though

      currently all routers allow only one concurrent sending connection */

    for (int i=0; i<this.sendingConnections.size(); ) {

        boolean removeCurrent = false;

        Connection con = sendingConnections.get(i);

 

        /*** 1. 处理已完成传输的数据包 ***/

        if (con.isMessageTransferred()) {

            if (con.getMessage() != null) {

                transferDone(con);

                con.finalizeTransfer();

            }

            removeCurrent = true;

        }

        /*** 2. 中止那些断开链路上的数据包 ***/

        else if (!con.isUp()) {

            if (con.getMessage() != null) {

                transferAborted(con);

                con.abortTransfer();

            }

            removeCurrent = true;

        }

 

        /*** 3. 必要时,删除那些最早接收到且不正在传输的消息 ***/

        if (removeCurrent) {

            if (this.getFreeBufferSize() < 0) {

                this.makeRoomForMessage(0);  //必要时,删除那些最早接收到且不正在传输的消息

            }

            sendingConnections.remove(i);

        } else {

            i++;  //index increase needed only if nothing was removed

        }

    }

 

    /*** 4. 丢弃那些TTL到期的数据包(只在没有消息发送的情况) ***/

    if (SimClock.getTime() - lastTtlCheck >= ttlCheckInterval && sendingConnections.size() == 0) {

        dropExpiredMessages();

        lastTtlCheck = SimClock.getTime();

    }

 

    /*** 5. 更新能量模板 ***/

    if (energy != null) {

        /* TODO: add support for other interfaces */

        NetworkInterface iface = getHost().getInterface(1);

        energy.update(iface, getHost().getComBus());

    }

}

由上可见,ActiveRouter.update主要做以下4件事:

1) 处理已完成传输的数据;

2) 中止那些断开链路上的数据包;

3) 必要时,删除那些最早接收到且不正在传输的消息;

4) 丢弃那些TTL到期的数据包(只在没有消息发送的情况)。

1.4 isTransferringcanStartTransfer

判断该节点能否进行传输消息,存在以下情况一种以上的,直接返回,不更新:

1) 本节点正在传输,sendingConnections.size() > 0

2) 没有邻居节点,即没有节点与之建立连接,connections.size() == 0

3) 有邻居节点,但有链路正在传输(想想无线信道),!con.isReadyForTransfer()

4) 缓冲区没有消息,this.getNrofMessages() == 0

1.5 isTransferring

isTransferring涵盖了上述的前3种情况,其源代码如下:

//ActiveRouter.java

public boolean isTransferring() {

    //情形1:本节点正在传输

    if (this.sendingConnections.size() > 0) {

        return true;

    }

 

    List<Connection> connections = getConnections();

 

    //情型2:没有邻居节点

    if (connections.size() == 0) {

        return false;

    }

 

    //情型3:有邻居节点,但有链路正在传输

    for (int i=0, n=connections.size(); i<n; i++) {

        Connection con = connections.get(i);

        if (!con.isReadyForTransfer()) {

            return true;

        }

    }

 

    return false;

}

只有当与邻居相连的所有链路都是空闲的,才能传输,这是因为无线的传输介质是广播的。而且每次传输只能有一个connection进行传输,可见The ONE仿真了无线信道,但其他没法收到这个广播包。

(1)判断链路是否空闲

The ONE的链路用Connection类表示,一条链路能用于传输需要同时满足两个条件:其一,该链路是建立的;其二,该链路是空闲的。相关成员变量如下:

//Connection.java

private boolean isUp;  //连接是否建立

protected Message msgOnFly; //连接是否被占用

(2)isReadyForTransfer

判断一条链路可否用于通信的源代码如下:

//Connection.java

public boolean isReadyForTransfer() {

    return this.isUp && this.msgOnFly == null;

}

1.6 canStartTransfer

canStartTransfer判断该节点能否开始传输,缓冲区有消息,并且有邻居节点,才返回真。源代码如下:

//ActiveRouter.java

protected boolean canStartTransfer() {

    if (this.getNrofMessages() == 0) {  //缓冲区空

        return false;

    }

    if (this.getConnections().size() == 0) { //没有连接建立,即没有邻居节点

        return false;

    }

 

    return true;

}

1.7 exchangeDeliverableMessages

exchangeDeliverableMessages用于交换该节点与邻居节点间的消息,这些消息的目的节点是该节点或者其邻居节点。该节点可能会有多个邻居节点(The ONE表示为多个connection),但只能让一个connection传输数据,想想无线信道。所以,只有有一个消息能传输到目的节点,就返回。exchangeDeliverableMessages先看本节点是否有消息的某个邻居节点,如果没有,再查看邻居节点是否有消息的目的节点是本节点。其源代码如下:

//ActiveRouter.java

protected Connection exchangeDeliverableMessages() {

    List<Connection> connections = getConnections();

    if (connections.size() == 0) {

        return null;

    }

 

    //getMessagesForConnected()返回那些目的节点就是邻居节点的消息

    //tryMessagesForConnected,尝试将上述返回的消息发送到目的节点(值得注意的是:只能发一个)

    Tuple<Message, Connection> t = tryMessagesForConnected(sortByQueueMode(getMessagesForConnected()));

    if (t != null) {

        return t.getValue(); // started transfer

    }

 

    //如果没发送成功,看邻居节点的缓冲区是否有消息的目的节点是该节点,若是,尝试传输

    for (Connection con : connections) {

        if (con.getOtherNode(getHost()).requestDeliverableMessages(con)) {

            return con;

        }

    }

 

    return null;

}

1.8 getMessagesForConnected

getMessagesForConnected返回本节点缓冲区的那些目的节点在其邻居节点的消息,这些消息只要投递成功,就成功达到目的节点。源代码如下:

//ActiveRouter.java

//返回那些消息的目的节点是某个邻居节点

protected List<Tuple<Message, Connection>> getMessagesForConnected() {

    if (getNrofMessages() == 0 || getConnections().size() == 0) {

        return new ArrayList<Tuple<Message, Connection>>(0);

    }

 

    List<Tuple<Message, Connection>> forTuples = new ArrayList<Tuple<Message, Connection>>();

    for (Message m : getMessageCollection()) {    //遍历缓冲区每个消息

        for (Connection con : getConnections()) { //遍历每个邻居节点

            DTNHost to = con.getOtherNode(getHost());

            if (m.getTo() == to) { //消息的目的节点是邻居节点

                forTuples.add(new Tuple<Message, Connection>(m,con));

            }

        }

    }

 

    return forTuples;

}

1.9 tryMessagesForConnected

tryMessagesForConnected尝试着将消息传输出去,只要有一个成功(意味着该信道被占用),就返回。

1.10 requestDeliverableMessages

requestDeliverableMessages如果本节点没有消息的目的节点是邻居节点,那么看看邻居节点是否有消息的目的节点在本节点。DTNHost的requestDeliverableMessages调用ActiveRouter的requestDeliverableMessages。源代码如下:

//ActiveRouter.java

public boolean requestDeliverableMessages(Connection con) {

    if (isTransferring()) {

        return false;

    }

 

    DTNHost other = con.getOtherNode(getHost()); //即得到本节点

 

    ArrayList<Message> temp = new ArrayList<Message>(this.getMessageCollection()); //do a copy to avoid concurrent modification exceptions (startTransfer may remove messages)

    for (Message m : temp) {

        if (other == m.getTo()) {

            if (startTransfer(m, con) == RCV_OK) {

                return true;

            }

        }

    }

    return false;

}

声明:之前学习参考了一位大牛的个人博客 ,但是时间久远找不到了,如果看到请与我联系,我会加上你博客网址,谢谢!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值