关于TheOne的仿真机制-由运动模型产生连接数据

/**
 * <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

关于TheOne的仿真机制-由运动模型产生连接数据

关于TheOne的仿真机制-由运动模型产生连接数据

上一篇:Photoshop制作菱形针织纹理无缝填充图案


下一篇:40个精彩的Illustrator英文教程