DirectDelivery路由策略很简单,每个节点携带自创建的消息,不断移动,直到遇到目的节点,才把消息传递出去,整个通信过程从不借助其他节点。这点方法优点很明显,开销是最低的,但缺点也很明显,效率是最低的。作为路由的一种极端,通常作为benchmark与其他协议进行比较。
DirectDeliveryRouter的继承关系是这样的:DirectDeliveryRouter —> ActiveRouter –> MessageRouter。update都会被重写并调用上一层的update。
相当于应用于的update,取决于具体应用,类似乎于事件处理函数取决于具体事件,其源代码如下:
//MessageRouter.java
public void update() {
for (Collection
for (Application app : apps) {
app.update(this.host);
}
}
}
ActiveRouter.update主要做4件事,其源代码如下:
//ActiveRouter.java
public void update() {
super.update(); //调用MessageRouter的update()
/* 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) 本节点正在传输,sendingConnections.size() > 0
2) 没有邻居节点,即没有节点与之建立连接,connections.size() == 0
3) 有邻居节点,但有链路正在传输(想想无线信道),!con.isReadyForTransfer()
4) 缓冲区没有消息,this.getNrofMessages() == 0
isTransferring涵盖了上述的前3种情况,其源代码如下:
//ActiveRouter.java
public boolean isTransferring() {
//情形1:本节点正在传输
if (this.sendingConnections.size() > 0) {
return true;
}
List
//情型2:没有邻居节点
if (connections.size() == 0) {
return false;
}
//情型3:有邻居节点,但有链路正在传输
for (int i=0, n=connections.size(); 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; } canStartTransfer判断该节点能否开始传输,缓冲区有消息,并且有邻居节点,才返回真。源代码如下: //ActiveRouter.java protected boolean canStartTransfer() { if (this.getNrofMessages() == 0) { //缓冲区空 return false; } if (this.getConnections().size() == 0) { //没有连接建立,即没有邻居节点 return false; } return true; } exchangeDeliverableMessages用于交换该节点与邻居节点间的消息,这些消息的目的节点是该节点或者其邻居节点。该节点可能会有多个邻居节点(The ONE表示为多个connection),但只能让一个connection传输数据,想想无线信道。所以,只有有一个消息能传输到目的节点,就返回。exchangeDeliverableMessages先看本节点是否有消息的某个邻居节点,如果没有,再查看邻居节点是否有消息的目的节点是本节点。其源代码如下: //ActiveRouter.java protected Connection exchangeDeliverableMessages() { List if (connections.size() == 0) { return null; } //getMessagesForConnected()返回那些目的节点就是邻居节点的消息 //tryMessagesForConnected,尝试将上述返回的消息发送到目的节点(值得注意的是:只能发一个) Tuple if (t != null) { return t.getValue(); // started transfer } //如果没发送成功,看邻居节点的缓冲区是否有消息的目的节点是该节点,若是,尝试传输 for (Connection con : connections) { if (con.getOtherNode(getHost()).requestDeliverableMessages(con)) { return con; } } return null; } getMessagesForConnected返回本节点缓冲区的那些目的节点在其邻居节点的消息,这些消息只要投递成功,就成功达到目的节点。源代码如下: //ActiveRouter.java //返回那些消息的目的节点是某个邻居节点 protected List if (getNrofMessages() == 0 || getConnections().size() == 0) { return new ArrayList } List for (Message m : getMessageCollection()) { //遍历缓冲区每个消息 for (Connection con : getConnections()) { //遍历每个邻居节点 DTNHost to = con.getOtherNode(getHost()); if (m.getTo() == to) { //消息的目的节点是邻居节点 forTuples.add(new Tuple } } } return forTuples; } tryMessagesForConnected尝试着将消息传输出去,只要有一个成功(意味着该信道被占用),就返回。 requestDeliverableMessages如果本节点没有消息的目的节点是邻居节点,那么看看邻居节点是否有消息的目的节点在本节点。DTNHost的requestDeliverableMessages调用ActiveRouter的requestDeliverableMessages。源代码如下: //ActiveRouter.java public boolean requestDeliverableMessages(Connection con) { if (isTransferring()) { return false; } DTNHost other = con.getOtherNode(getHost()); //即得到本节点 ArrayList for (Message m : temp) { if (other == m.getTo()) { if (startTransfer(m, con) == RCV_OK) { return true; } } } return false; } 声明:之前学习参考了一位大牛的个人博客 ,但是时间久远找不到了,如果看到请与我联系,我会加上你博客网址,谢谢!1.6 canStartTransfer
1.7 exchangeDeliverableMessages
1.8 getMessagesForConnected
1.9 tryMessagesForConnected
1.10 requestDeliverableMessages