Simulation of Transmission and Propagation Delay in Packet-switched Networks
这是"Computer Networking"中的一个仿真applet,我只是修改了其中关于线程suspend的部分。
看完代码的总体感觉是,仿真的思维方式就是,让用户能非常直观的看到过程和结果。为此付出的代价,真是巨大!
Basics:
transmission delay = packet length / transmission rate
propagation delay = distance / propagation speed
Result:
Source Code:
/////LineSimApllet//written by David Grangier, Institut Eurecom, France//david.grangier@eurecom.fr///package linesim;//importsimport java.awt.*;import java.awt.event.*;import java.awt.image.*;import java.applet.*;import java.util.*;//Applet Classpublic class LineSimApplet extends Applet { //buttons Button start=new Button ("Start"); Button stop=new Button ("Reset"); //features lists MyChoice length=new MyChoice(new String[] {"10 km","100 km","1000 km"},new double[] {10E3,100E3,1E6},3); MyChoice rate=new MyChoice(new String[] {"512 kps","1 Mbps","10 Mbps","100 Mbps"},new double[] {512E3,1E6,10E6,100E6},2); MyChoice size=new MyChoice(new String[] {"100 Bytes","500 Bytes","1 kBytes"},new double[] {8E2,4E3,8E3},1); //to simulate time Thread timerThread; TickTask timerTask; boolean simulationRunning=false; boolean simulationSuspend=false; //communication line Line myLine; public void init() { try { setBackground(Color.white); add(new Label ("Length",Label.RIGHT)); add(length); add(new Label("Rate",Label.RIGHT)); add(rate); add(new Label("Packet size",Label.RIGHT)); add(size); //start start.addActionListener( new ActionListener() { public void actionPerformed (ActionEvent event) { launchSim(); } }); add(start); //stop Button stop=new Button ("Reset"); stop.addActionListener( new ActionListener() { public void actionPerformed (ActionEvent event) { stopSim(); //clear line myLine.sendTime(0); //redraw cleared line LineSimApplet.this.repaint(); } }); add(stop); //line myLine= new Line(40,50,450,10); } catch(Exception e) { e.printStackTrace(); } } public void paint (Graphics g) { update(g); // eliminate flashing : update is overriden } public void update (Graphics g) { //work on a offscreen image Dimension offDimension = getSize(); Image offImage = createImage(offDimension.width, offDimension.height); Graphics offGraphics = offImage.getGraphics(); myLine.drawLine(offGraphics); //sender offGraphics.setColor(Color.blue); offGraphics.fillRect(10,40,30,30); offGraphics.setColor(Color.black); offGraphics.drawString("Sender",5,90); offGraphics.drawRect(10,40,30,30); //receiver offGraphics.setColor(Color.blue); offGraphics.fillRect(490,40,30,30); offGraphics.setColor(Color.black); offGraphics.drawString("Receiver",485,90); offGraphics.drawRect(490,40,30,30); offGraphics.drawString("Propagation speed : 2.8 x 10^8 m/sec",175,105); //display offscreen image g.drawImage(offImage, 0, 0, this); } private void launchSim() { setupEnabled(false); //setup line myLine.setup(length.getVal(), rate.getVal() ); myLine.emitPacket(size.getVal(),0); //setup timer timerTask=new TickTask(1E-5,myLine.totalTime()); timerThread=new Thread(timerTask); //start simulation simulationRunning=true; simulationSuspend=false; timerThread.start(); } private void stopSim() { timerTask.endNow(); simulationRunning=false; setupEnabled(true); } public void setupEnabled(boolean value) { start.setEnabled(value); length.setEnabled(value); rate.setEnabled(value); size.setEnabled(value); } //my choice class MyChoice extends Choice { private double vals[]; public MyChoice(String items[], double values[],int defaultValue) { for (int i=0; i=length) { LineSimApplet.this.myLine.clearPackets(); LineSimApplet.this.simulationSuspend=true; } try {LineSimApplet.this.timerThread.sleep(50);} catch (Exception e) { } } else // suspend state { try {Thread.sleep(500);} catch(Exception e) {} } } } public void endNow() { length=counter; } }}//Line classclass Line{ //graphic variables private int gX; private int gY; private int gWidth; private int gHeight; //characteristic variables final double celerity = 2.8E+8; private double length; private double rate; //simulation variables private double time; private Packet myPacket; public Line(int x, int y, int w, int h) { //graphic init gX=x; gY=y; gWidth=w; gHeight=h; } public void setup(double l, double r) { length=l; rate=r; } void sendTime(double now) { time=now; //update time removeReceivedPackets(now); } void emitPacket(double s, double eT) { myPacket= new Packet(s,eT); } private void removeReceivedPackets(double now) { if (!(myPacket==null)) { if ( now>myPacket.emissionTime+(myPacket.size/rate)+length*celerity ) { clearPackets(); } } } public void clearPackets() { myPacket=null; } public double totalTime() { double emmissionTime=(myPacket.size/rate); double onLineTime=(length/celerity); return (emmissionTime+onLineTime); } public void drawLine(Graphics g) { g.setColor(Color.white); g.fillRect(gX,gY+1,gWidth,gHeight-2); g.setColor(Color.black); g.drawRect(gX,gY,gWidth,gHeight); g.setColor(Color.red); g.drawString(timeToString(time),gX+gWidth/2-10,gY+gHeight+15); drawPackets(g); } private void drawPackets(Graphics g) { if (!(myPacket==null)) { double xfirst; double xlast; //compute time units xfirst=time-myPacket.emissionTime; xlast=xfirst-(myPacket.size/rate); //compute position xfirst=xfirst*celerity*gWidth/length; xlast=xlast*celerity*gWidth/length; if (xlast<0) {xlast=0;} if (xfirst>gWidth ) {xfirst=gWidth;} //draw g.setColor(Color.red); g.fillRect(gX+(int)(xlast),gY+1,(int)(xfirst-xlast),gHeight-2); } } static private String timeToString(double now) { String res=Double.toString(now*1000); int dot=res.indexOf('.'); String deci=res.substring(dot+1)+"000"; deci=deci.substring(0,3); String inte=res.substring(0,dot); return inte+"."+deci+" ms"; }}class Packet{ double size; double emissionTime; Packet(double s, double eT) { size=s; emissionTime=eT; }}