TheONE_消息转发流程分析(1)

来源:http://blog.sina.com.cn/s/blog_48ded66a01018sho.html

**TheONE_消息转发流程分析(1)**

TheONE全称为The Opportunistic Network Environment simulator,是一款Java平台的容迟网络仿真软件,本文采用一条纵线分析了TheONE中消息转发的流程。

****1. 消息转发的入口*****

跟踪发包流程最主要的是找到入口,ONE与NS2最大的区别在于:NS2是离散事件驱动的,而ONE采用的是周期更新即Update,如果把网络中的事件比喻成出门坐车,那么NS2像是打车,招手即停,而ONE是坐公交,公交车每隔一段时间来一班,这个时间间隔就是Update的周期,在default_setting.txt中定义为0.1秒。于是最先要找到的就是update函数。ONE核心的功能可以看作由两大部分组成,一是移动,二是消息转发,简而言之,前者根据移动模型确定下一时段各节点的位置坐标,后者根据接口和路由来决定节点是否应该收到一个消息。本文讨论的是消息转发流程,因此忽略节点移动部分,直接找到消息转发的入口。

DTNHost是ONE中最基本的类,它定义了一个节点(后文将节点与Host等同)的基本属性和基本功能,在DTNHost.java中的update()函数负责更新网络接口和路由。

public void update(boolean simulateConnections) {

      if (!isActive()) {                         //如果节点处于非激活状态,则不会执行后面的语句

          return;                                //可以将非激活状态想象成一个自私节点或者没电的传感器

      }

      if (simulateConnections) {

          for (NetworkInterface i : net) {

             i.update();     //更新所有的接口

          }

      }

      this.router.update();   //更新路由

   }

可以看出在update()中先更新了接口,后更新了路由,原因是路由的工作需要建立在接口的基础之上。本文也先说接口,后说路由。

2. 维护有效的连接

首先要解释ONE中的一个最基本的概念——连接(Connection/Connect)。由于ONE并不侧重于底层信道的仿真,因此空中接口的概念已经淡化了,取而代之的是“连接”。简单的理解,当两个节点在彼此通信范围之内,连接就认为是建立的,ONE习惯中用UP表示,反之用DOWN。ONE中提供了一系列函数用于维护所有节点之间的连接。详细情况可以读一下connection.java。一个最基本的连接包括了:

 protected DTNHost toNode;                //连接的目的节点

   protected NetworkInterface toInterface;   //连接的目的接口

   protected DTNHost fromNode;              //链接的源节点

   protected NetworkInterface fromInterface; //链接的源接口

   protected DTNHost msgFromNode;           //消息的源节点

   private boolean isUp;                    //最重要的是连接的当前状态

   protectedMessage msgOnFly;              //连接正在传输的消息
实际上,仿真中通常使用的是CBRConnection类,这个类继承自Connection,扩展了:

 

   private int speed;                    //CBR流的传输速度

   private double transferDoneTime;      //传输完成的时间
回到update的问题上,更新接口执行的是网络接口的更新函数,在NetworkInterface类中update()是一个空函数,实际上更新的是它子类中的update()函数。在实际仿真中,经常采用SimpleBroadcastInterface作为接口类型(实际上ONE也没给我们太多的选择),因此SimpleBroadcastInterface.java中的更新函数是维护连接的关键。

 

   

   public void update() {

      // First break the old ones

      optimizer.updateLocation(this);

      for (int i=0; i<</span>this.connections.size(); ) {    //遍历所有连接

          Connection con = this.connections.get(i);

          NetworkInterface anotherInterface = con.getOtherInterface(this);

          // all connections should be up at this stage

          assert con.isUp() : "Connection " + con + " was down!";

 

          if (!isWithinRange(anotherInterface)) {      //删除已经断开的连接

             disconnect(con,anotherInterface);

             connections.remove(i);

          }

          else {

             i++;

          }

      }

      // Then find new possible connections

      Collection interfaces =

          optimizer.getNearInterfaces(this);

      for (NetworkInterface i : interfaces) {      //建立新的连接

          connect(i);

      }

   }

 

这个函数的思想很简单,首先检索所有已经建立好的连接,将其中已经断开的连接删除,再找到新的可以建立的连接。这路重点需要看的是两个函数:

isWithinRange()目的是判断两个接口所在的节点是否在彼此的通信范围之内,这个函数是路由与移动模型交互的地方,在仿真脚本中设置的接口传输距离、移动模型都会最这个函数的返回值产生影响。

connect()函数是建立连接的函数,在SimpleBroadcastInterface类中,建立连接并不简单,需要满足一系列条件才能建立,这些条件主要是:确保接口处于扫描状态、确保节点处于活跃状态、确保两接口所在节点彼此能通信、确保两接口不是已经连接的、确保两接口不是同一接口:
 

public void connect(NetworkInterface anotherInterface) {

          if (isScanning()

                 && anotherInterface.getHost().isActive()

                 && isWithinRange(anotherInterface)

                 && !isConnected(anotherInterface)

                 && (this != anotherInterface)) {
满足这些条件的两个接口能够成功建立连接,连接建立的过程包括:将连接con添加到本节点和对方节点的connections中、将本节点和对方节点con的状态设置为UP、通知Listener连接con已经建立。在ONE中,多种Listener用于统计网络性能,生成Reports,刚开始看代码的时候,可以将所有与Listener有关的语句都忽略。

 

   protected void connect(Connection con, NetworkInterface anotherInterface) {

      this.connections.add(con);

      notifyConnectionListeners(CON_UP, anotherInterface.getHost());

 

      // set up bidirectional connection

      anotherInterface.getConnections().add(con);

 

      // inform routers about the connection

      this.host.connectionUp(con);

      anotherInterface.getHost().connectionUp(con);

   }

连接维护的实际过程要比上面所说的稍复杂,但核心思想很简单:节点周期检查自己与周围节点的位置,与满足传输条件的节点的对应接口建立连接。需要补充的是,连接的建立实际上是以接口为单位的,不是与节点为单位的,因为一个节点可以有多个接口,而不同种类接口的传输距离不同。

上一篇:【洛谷6940】[ICPC2017 WF] Visual Python++(扫描线)


下一篇:【洛谷6896】[ICPC2014 WF] Maze Reduction(哈希)