/** * <P> * Overlay grid of the world where each interface is put on a cell depending * of its location. This is used in cell-based optimization of connecting * the interfaces.</P> * * <P>The idea in short:<BR> * Instead of checking for every interface if some of the other interfaces are close * enough (this approach obviously doesn‘t scale) we check only interfaces that * are "close enough" to be possibly connected. Being close enough is * determined by keeping track of the approximate location of the interfaces * by storing them in overlay grid‘s cells and updating the cell information * every time the interfaces move. If two interfaces are in the same cell or in * neighboring cells, they have a chance of being close enough for * connection. Then only that subset of interfaces is checked for possible * connectivity. * </P> * <P> * <strong>Note:</strong> this class does NOT support negative * coordinates. Also, it makes sense to normalize the coordinates to start * from zero to conserve memory. */ public class ConnectivityGrid extends ConnectivityOptimizer {
上面是TheOne中对连接网格的介绍,节点运动对应坐标改变,坐标改变需要更新连接关系,对于某一个节点来说,如果没有连接网格的支持,需要遍历所有的节点来判断两者是否满足传输range的要求,来决定能否建立connection,这显然不可扩展scale,因为随着网络的增大,这种检测将变得不可行。
所以采用一种网格,将节点对应到网格内,这样每次检测某个节点能否和其它节点建立连接,只需要检测本网格和邻居网络的节点即可。
有点类似Opnet的rxgroup。
/** * Notifies all the connection listeners about a change in connections. * @param type Type of the change (e.g. {@link #CON_DOWN} ) * @param otherHost The other host on the other end of the connection. */ private void notifyConnectionListeners(int type, DTNHost otherHost) { if (this.cListeners == null) { return; } for (ConnectionListener cl : this.cListeners) { switch (type) { case CON_UP: cl.hostsConnected(this.host, otherHost); break; case CON_DOWN: cl.hostsDisconnected(this.host, otherHost); break; default: assert false : type; // invalid type code } } }上面的代码是在NetworkInterface下,能够通知所有的连接监听成员当前连接的变化情况。
# The Tram groups Group4.groupID = t Group4.bufferSize = 50M Group4.movementModel = MapRouteMovement Group4.routeFile = data/tram3.wkt Group4.routeType = 1 Group4.waitTime = 10, 30 Group4.speed = 7, 10 Group4.nrofHosts = 2 Group4.nrofInterfaces = 2 Group4.interface1 = btInterface Group4.interface2 = highspeedInterface
一个节点可能有多个接口,比如上面默认配置文件中的Tram有连个interface,一个蓝牙,一个高速接口
整个运行流程:
GUI运行runSim,运行world.update,其中运行updateHosts,其中运行更新网络接口连接和路由模块,相当于是由节点的运动来驱动整个连接数据的更新和路由的运行。
DTNSim.java中调用:
new DTNSimGUI().start();
public void start() { initModel(); runSim(); }
/** * Initializes the simulator model. */ private void initModel() { Settings settings = null; try { settings = new Settings(); this.scen = SimScenario.getInstance();
/** * Returns the SimScenario instance and creates one if it doesn‘t exist yet */ public static SimScenario getInstance() { if (myinstance == null) { myinstance = new SimScenario(); } return myinstance; }
/** * Creates a scenario based on Settings object. */ protected SimScenario() { Settings s = new Settings(SCENARIO_NS); nrofGroups = s.getInt(NROF_GROUPS_S); this.name = s.valueFillString(s.getSetting(NAME_S)); this.endTime = s.getDouble(END_TIME_S); this.updateInterval = s.getDouble(UP_INT_S); this.simulateConnections = s.getBoolean(SIM_CON_S); ensurePositiveValue(nrofGroups, NROF_GROUPS_S); ensurePositiveValue(endTime, END_TIME_S); ensurePositiveValue(updateInterval, UP_INT_S); this.simMap = null; this.maxHostRange = 1; this.connectionListeners = new ArrayList<ConnectionListener>(); this.messageListeners = new ArrayList<MessageListener>(); this.movementListeners = new ArrayList<MovementListener>(); this.updateListeners = new ArrayList<UpdateListener>(); this.appListeners = new ArrayList<ApplicationListener>(); this.eqHandler = new EventQueueHandler(); /* TODO: check size from movement models */ s.setNameSpace(MovementModel.MOVEMENT_MODEL_NS); int [] worldSize = s.getCsvInts(MovementModel.WORLD_SIZE, 2); this.worldSizeX = worldSize[0]; this.worldSizeY = worldSize[1]; createHosts(); this.world = new World(hosts, worldSizeX, worldSizeY, updateInterval, updateListeners, simulateConnections, eqHandler.getEventQueues()); }
runSim函数:
protected void runSim() { double simTime = SimClock.getTime(); double endTime = scen.getEndTime(); startGUI(); // Startup DTN2Manager // XXX: Would be nice if this wasn‘t needed.. DTN2Manager.setup(world); while (simTime < endTime && !simCancelled){ if (guiControls.isPaused()) { wait(10); // release CPU resources when paused } else { try { world.update(); } catch (AssertionError e) { // handles both assertion errors and SimErrors processAssertionError(e); } simTime = SimClock.getTime(); } this.update(false); }
world.update():
/** * Update (move, connect, disconnect etc.) all hosts in the world. * Runs all external events that are due between the time when * this method is called and after one update interval. */ public void update () { double runUntil = SimClock.getTime() + this.updateInterval; setNextEventQueue(); /* process all events that are due until next interval update */ while (this.nextQueueEventTime <= runUntil) { simClock.setTime(this.nextQueueEventTime); ExternalEvent ee = this.nextEventQueue.nextEvent(); ee.processEvent(this); updateHosts(); // update all hosts after every event setNextEventQueue(); } moveHosts(this.updateInterval); simClock.setTime(runUntil); updateHosts(); /* inform all update listeners */ for (UpdateListener ul : this.updateListeners) { ul.updated(this.hosts); } }
updateHosts():
/** * Updates all hosts (calls update for every one of them). If update * order randomizing is on (updateOrder array is defined), the calls * are made in random order. */ private void updateHosts() { if (this.updateOrder == null) { // randomizing is off for (int i=0, n = hosts.size();i < n; i++) { if (this.isCancelled) { break; } hosts.get(i).update(simulateConnections); } }
hosts.get(i).update(simulateConnections); 更新所有的网络接口和路由模块,网络接口即链路连接数据
/** * Updates node‘s network layer and router. * @param simulateConnections Should network layer be updated too */ public void update(boolean simulateConnections) { if (!isActive()) { return; } if (simulateConnections) { for (NetworkInterface i : net) { i.update(); } } this.router.update(); }
路由更新的是如下函数,在message router中,所有router的母类,所有router(Active, epedemic)都要执行父类的super.update()
/** * Updates router. * This method should be called (at least once) on every simulation * interval to update the status of transfer(s). */ public void update(){ for (Collection<Application> apps : this.applications.values()) { for (Application app : apps) { app.update(this.host); } } }
在路由模块中会更新host,app.update(this.host);
for (NetworkInterface i : net) { i.update();
NetworkInterface 会更新,比如这个是SimpleBroadcastInterfaceextends NetworkInterface,首先会断掉超出距离的连接,然后会找新的连接,这里用到了连接网格优化器:optimizer.getNearInterfaces(this); 通过这个函数返回所有可能建立连接的网络接口
/** * Updates the state of current connections (ie tears down connections * that are out of range). */ public void update() { // First break the old ones optimizer.updateLocation(this); for (int i=0; i<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<NetworkInterface> interfaces = optimizer.getNearInterfaces(this); for (NetworkInterface i : interfaces) { connect(i); } }
SimpleBroadcastInterface 的connect会判断一系列条件来决定新的连接是否可能,比如是否正在扫描(似乎使用了蓝牙的周期性扫描的功能)、另一个连接是否激活、是否在相应范围内、是否与其它接口连接了,都满足条件,才会建立连接,建立了一个CBR连接
/** * Tries to connect this host to another host. The other host must be * active and within range of this host for the connection to succeed. * @param anotherInterface The interface to connect to */ public void connect(NetworkInterface anotherInterface) { if (isScanning() && anotherInterface.getHost().isActive() && isWithinRange(anotherInterface) && !isConnected(anotherInterface) && (this != anotherInterface)) { // new contact within range // connection speed is the lower one of the two speeds int conSpeed = anotherInterface.getTransmitSpeed(); if (conSpeed > this.transmitSpeed) { conSpeed = this.transmitSpeed; } Connection con = new CBRConnection(this.host, this, anotherInterface.getHost(), anotherInterface, conSpeed); connect(con,anotherInterface); } }最后调用基类NetworkInterface的connect函数:connect(con,anotherInterface); 因为参数不同,可以用相同的函数名
/** * Connects this host to another host. The derived class should check * that all pre-requisites for making a connection are satisfied before * actually connecting. * @param con The new connection object * @param anotherInterface The interface to connect to */ 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); }
最后上一张one结构图,来源:http://www.cnblogs.com/dreamfactory/archive/2012/07/27/2612215.html