1、网络仿真和模拟课程设计实验报告 学院: 计算机学院 专业: 网络工程 组员(学号): 指导老师: 完成时间 2016年6月30日 2目录网络仿真和模拟课程设计实验报告1目录2一、NS2模拟环境搭建11.1安装cygwin11.2安装NS26二、不同版本的TCP协议仿真模拟92.1实验目的92.1实验步骤92.2实验过程及结果比较9三、添加Ping协议163.1实验目的163.2 实验步骤16四、添加Application和Agent协议214.1实验目的214.2实验步骤21附录A27附录B30附录C34附录D44附录E45附录F48网络仿真和模拟课程设计手册一、NS2模拟环境搭建在Windo
2、ws操作系统下安装比较繁琐,需要根据NS不同版本,下载相关补丁进行修正。下面介绍在Windows下安装NS-allinone过程。1.1安装cygwin1) 点击安装setup.exe文件,如图1所示:图1 执行setup.exe文件2) 请点击“下一步”按钮,如图2所示:图2 安装步骤23) 选择“Install from Internet”单选按钮,如图3所示:图3 安装步骤34) 点击“下一步”按钮,如图4所示:图4 安装步骤45) 点击“下一步”按钮,如图5所示:图5 安装步骤56) 点击“下一步”按钮,如图6所示:图6 安装步骤67) 点击“下一步”按钮,如图7所示:图7 安装步骤7
3、8) 点击“下一步”按钮,如图8所示:图8 安装步骤89) 选择“Curr”,点击“View”按钮,使右方出现“full”,然后把最下角的隐藏过期包组件那个勾去掉,如图9所示:图9 安装步骤910) 由于是初次接触该软件,在不清楚各个包作用的情况下将所有的包都安装,然后点击“下一步”按钮,如图10所示:图10 安装步骤1011) 安装结束后,点击“完成”按钮,如图11所示:图11 安装步骤111.2安装NS21) 解压缩并改变路径到ns-allinone-2.35,如图12所示:图12 切换到NS目录2) 修改ls.h错误代码行(进入C:cygwinhome/Administartor/ns-
4、allinone -2.35/ns-2.35/linkstate/ls.h 第137行):3) 安装指令,进行编译安装,如图13所示:图13 进行编译安装4) 重新编译完后,如图14所示:图14 编译结果5) 设置环境变量:6) 测试NS2是否安装成功,如图15所示:图15 进入图形化接口窗口7) 在跳出的对话框中,输入nam,系统跳出一个图形界面,如图16所示:图16 Nam界面8) 在窗口中输入gnuplot,结果如图17所示,则NS2安装成功:图17 gnuplot界面二、不同版本的TCP协议仿真模拟2.1实验目的通过本实验了解如何利用OTcl脚本编写NS仿真案例。2.1实验步骤l NS
5、2下不同版本的TCP协议的OTcl脚本编写。l 在winx-server模式下键入命令:ns 运行ns文件。l 对实验结果进行分析比较。2.2实验过程及结果比较n Tahoe执行方法,如下所示:1. ns lab11.tcl Tahoe (lab11.tcl文件代码参考附录A ,TCPV1)2. gnuplot 进入gnuplot提示符会在目录下生成gif 图片,见下面图片比较。n Reno执行方法,如下所示:n NewReno执行方法,如下所示:(lab12.tcl)n SACK执行方法,如下所示:n Vegas执行方法,如下所示:(lab13_1.tcl)gnuplot set title
6、 “Vegas”gnuplot set xlabel “time”gnuplot set ylabel “cwnd”gnuplot set terminal gifgnuplot set output “cwnd-Vegas”gnuplotplot “cwnd0.tr” with linespoints lt 1, “cwnd1.tr” with linespoints lt 2n Vegas和 Re执行方法,如下所示:(lab13_2.tcl)1 . ns lab13_2.tcl2.gnuplot set title “Vegas vs Reno”gnuplot set xlabel “ti
7、me”gnuplot set ylabel “cwnd”gnuplot set terminal gifgnuplot set output “cwnd-Vegas-Reno”gnuplotplot “cwnd-vegas.tr” with linespoints lt 1, “cwnd-reno.tr” with linespoints lt n 结果比较图16 Tahoe的cwnd变化图图17 Reno的cwnd变化图图18 TCP NewReno图19 SACK图20 Vegas图形图21 Vegas与Reno的cwnd变化图n 结果分析从Tahoe的cwnd变化图(图16)中我们可以看
8、出,TCP的Congestion Window值会呈现周期性的重复变化。开始时,先由Slow-start开始,cwnd超过Ssthresh时进入Congestion Avoidance阶段。由于传送到网络上的封包不断地增加,当超出允许能传送到网络上的个数时,路由器开始使用Drop-tail将封包丢掉。当有封包遗失时,Tahoe这个TCP版本会将ssthresh设为发现到封包遗失时的Window值的1/2,接着将Window的值设为1。在Tahoe这个例子中,由于只要有封包遗失,Cwnd的值就会被重置为1(小于Ssthresh),因此每次封包遗失,Tahoe都重新由slow-start开始。从R
9、eno的cwnd变化图(图17)中看到,当检测到封包遗失时,ssthresh和cwnd的值会被设为先前cwnd值的1/2。因此在重送遗失的封包后,TCP Reno会由Congestion Avoidance开始。由于结束Fast recovery后,Reno的cwnd由先前cwnd值的1/2开始增加,所以得到的平均吞吐量较Tahoe为佳。从该图中我们还可以看到,当TCP的传送端观察到端点到端点的路径并没有拥塞的情况时(没有检测到封包遗失),会持续地以累加的方式增加传送速率。但是当检测到路径拥塞的情况时,则以倍数的方式减少传送速率。基于上述原因,TCP的拥塞控制算法又常被称为累加递增-倍数递减的
10、算法。从TCP NewReno的cwnd变化图(图18)中我们可以看到,NewReno在收到Partial ACK时,并不会立刻结束Fast-recovery,相反,NewReno的传送端会持续地重送Partial ACK之后的封包,直到将所有遗失的封包重送后才会结束Fast-recovery,这使得NewReno的传送端在网络有大量封包遗失时不需等待Timeout就能更正此错误,减少大量封包遗失对传输效果所造成的影响。NewReno大约每一个RTT时间可重送一个遗失的封包,在Fast-recovery阶段,若允许的话,传送端可以继续送出新的封包,以增加Link的使用率。从TCP SACK的c
11、wnd变化图(图19)中我们可以看到,在这个版本中,加入了一个SACK选项,允许接收端在返回Duplicate ACK时,将已接收到的数据区段(连续收到的数据范围)返回给传送端,数据区段与数据区段之间的间隔就是接收端没有收到的数据。通过这些信息,传送端就知道哪些是已经收到的,哪些是该重送的,因此SACK的传送端可以在一个RTT时间之内重送一个以上的封包。从Vegas的图形(图20)中可以看到,第一条Vegas从0s开始执行,10s时结束。第二条Vegas在5s时才开始执行,10s时结束。从图中我们还可以看到,在Slow-start阶段,cwnd的值大约两个RTT才会增加1倍。与Reno不同的是
12、,当Diff的值介于与之间时,Vegas的cwnd会持续维持在一个稳定的状态,这是因为,基本上Vegas的拥塞控制算法是一种“拥塞避免”的方法。从Vegas与Reno的cwnd的变化图(图21)中可以看到,Reno的Window总是在较高的地方振荡,而Vegas的Window总是在较低的位置。虽然根据研究显示,当网络的通信都使用TCP Vegas时,整体的执行效果会优于TCP Reno,这是因为TCP Vegas采取较为保守的作法避免封包遗失,并以此提高网络的执行效果。但当TCP Vegas和Reno共存时,TCP Vegas并没有办法与TCP Reno公平地竞争频宽。造成这个问题的主要原因是
13、,Reno使用了较具侵略性的拥塞控制方法,TCP Reno的传送端会持续地将封包送到网络上直到发生拥塞。比较之下,Vegas的传送端在网络开始拥塞时就将传送端的传送速度降慢,以避免拥塞的情形发生。因此,当TCP Vegas与TCP Reno共存Vegas在效果上的表现总是会比较差。三、添加Ping协议3.1实验目的本实验通过实现一个Ping协议来说明如何在NS2中添加新协议3.2 实验步骤一、在ns-2.35目录下新建一个MyPing目录,将老师给的文件MyPing.h和MyPing.cc放到这个目录里下。这两个文件见 附录D和E。(红色字体为修订处)文件说明:MyPing.h中 :定义了包头
14、结构:struct hdr_ping char ret; double send_time;定义PingAgent类class PingAgent : public Agent public: PingAgent(); int command(int argc, const char*const* argv); void recv(Packet*, Handler*); protected: int off_ping_;MyPing.cc中: 定义PingHeaderClass类static class PingHeaderClass : public PacketHeaderClass pu
15、blic: PingHeaderClass() : PacketHeaderClass(PacketHeader/Ping, sizeof(hdr_ping) class_pinghdr;定义PingClass类static class PingClass : public TclClass public: PingClass() : TclClass(Agent/Ping) TclObject* create(int, const char*const*) return (new PingAgent(); class_ping;定义PingAgent的实现PingAgent:PingAgen
16、t() : Agent(PT_PING) bind(packetSize_, &size_); bind(off_ping_, &off_ping_);int PingAgent:command(int argc, const char*const* argv) if (argc = 2) if (strcmp(argv1, send) = 0) return (Agent:command(argc, argv);void PingAgent:recv(Packet* pkt, Handler*)二、修改ns-2.35/common/packet.h文件如图找到相应的地方添加修改:(代码前面的
17、 + 表示添加,-表示删除,下同)三、编辑ns-2.35/tcl/lib/ns-default.tcl增加一行 Agent/MyPing set packetSize_ 64四、编辑ns-2.35/Makefile文件如图在 OBJ_CC 下添加一行五、Makefile目录下编译文件make cleanmake dependmake 六、编写测试的TCL代码#Create a simulator objectset ns new Simulator#Open a trace fileset nf open out.nam w$ns namtrace-all $nf#Define a finis
18、h procedureproc finish global ns nf $ns flush-trace close $nf exec nam out.nam & exit 0#Create three nodesset n0 $ns nodeset n1 $ns nodeset n2 $ns node#Connect the nodes with two links$ns duplex-link $n0 $n1 1Mb 10ms DropTail$ns duplex-link $n1 $n2 1Mb 10ms DropTail#Define a recv function for the cl
19、ass Agent/MyPingAgent/MyPing instproc recv from rtt $self instvar node_puts node $node_ id received ping answer from $from with round-trip-time $rtt ms.#Create two ping agents and attach them to the nodes n0 and n2set p0 new Agent/MyPing$ns attach-agent $n0 $p0set p1 new Agent/MyPing$ns attach-agent
20、 $n2 $p1#Connect the two agents$ns connect $p0 $p1#Schedule events$ns at 0.2 $p0 send$ns at 0.4 $p1 send$ns at 0.6 $p0 send$ns at 0.6 $p1 send$ns at 1.0 finish#Run the simulation$ns run七、运行代码四、添加Application和Agent协议4.1实验目的本部分通过编写一个UDP上的multimedia Application来说明如何添加Application和Agent4.2实验步骤一、在ns-2.35下新
21、建目录Multimedia,将udp-mm.cc,udp-mm.h,mm-app.cc,mm-app.h 四个文件放到该目录下,这四个文件详细见 附录F。文件说明:其中定义包头结构编写MmApp Sender编写MmApp Receiver具体见附录。编写UdpMmAgentUdpMmAgent继承了UdpAgent,添加了部分功能。具体见附录。二、修改ns-2.35/packet.h在如图两处,各添加一行,并做相应修改。三、修改ns-2.35/tcl/lib/ns-packet.tcl在protolist里添加四、修改ns-2.35/common/agent.h五、修改 ns-2.35/ap
22、ps/app.h:六、在ns-2.35/tcl/lib/ns-default.tcl 中设置新参数的默认值七、 编辑ns-2.35/Makefile :八、在Makeflie目录下编译: make cleanmake dependmake九、运行编写测试的TCL代码 。 见附录F :ex-mm-app.tcl十、运行程序 ns ex-mm-app.tcl附录ATCPV1代码if $argc !=1 puts Usage: ns lab11.tcl TCPversion puts Example:ns lab11.tcl Tahoe or ns lab11.tcl Renoexitset par
23、1 lindex $argv 0# 产生一个仿真的对象set ns new Simulator$ns color 1 Blue#开启一个trace file,用来记录封包传送的过程set nd open out-$par1.tr w$ns trace-all $ndset nf open out-$par1.nam w$ns namtrace-all $nf#开启一个档案用来记录cwnd变化情况set f0 open cwnd-$par1.tr w#定义一个结束的程序proc finish global ns nd nf f0 tcp par1 #显示最后的平均吞吐量 puts format
24、average throughput:%.1f Kbps expr $tcp set ack_*($tcp set packetSize_)*8/1000.0/10 $ns flush-trace#关闭档案 close $ndclose $nf close $f0exec nam out-$par1.nam & exit 0#定义一个记录的程序#每格0.01秒就去记录当时的cwndproc record global ns tcp f0set now $ns nowputs $f0 $now $tcp set cwnd_$ns at expr $now+0.01 record#产生传送节点,路
25、由器r1,r2和接收节点set n0 $ns nodeset r0 $ns nodeset r1 $ns nodeset n1 $ns node#建立链路$ns duplex-link $n0 $r0 10Mb 1ms DropTail$ns duplex-link $r0 $r1 1Mb 4ms DropTail$ns duplex-link $r1 $n1 10Mb 1ms DropTail$ns duplex-link-op $n0 $r0 orient right$ns duplex-link-op $r0 $r1 orient right$ns duplex-link-op $r1
26、$n1 orient right$ns duplex-link-op $r0 $r1 queuePos 0.5#设定队列长度为18个封包大小set queue 18$ns queue-limit $r0 $r1 $queue#根据使用者的设定,指定TCP版本if $par1=Tahoe set tcp new Agent/TCP else set tcp new Agent/TCP/Reno$ns attach-agent $n0 $tcpset tcpsink new Agent/TCPSink$ns attach-agent $n1 $tcpsink$ns connect $tcp $tc
27、psink$tcp set fid_ 1#建立FTP应用程序set ftp new Application/FTP$ftp attach-agent $tcp#在0.0秒时,开始传送$ns at 0.0 $ftp start#在10.0秒时,结束传送$ns at 10.0 $ftp stop#在0.0秒时去呼叫record来记录TCP的cwnd变化情况$ns at 0.0 record#在第10.0秒时去呼叫finish来结束模拟$ns at 10.0 finish#执行模拟$ns run附录BTCPV2代码if $argc !=1 puts Usage: ns lab12.tcl TCPve
28、rsion puts Example:ns lab12.tcl Reno or ns lab12.tcl Newreno or ns lab12.tcl Sackexitset par1 lindex $argv 0# 产生一个仿真的对象set ns new Simulator#开启一个trace file,用来记录封包传送的过程set nd open out-$par1.tr w$ns trace-all $nd#开启一个档案用来记录cwnd变化情况set f0 open cwnd-$par1.tr w#定义一个结束的程序proc finish global ns nd f0 tcp par
29、1 #显示最后的平均吞吐量 puts format average throughput: %.1f Kbps expr $tcp set ack_*($tcp set packetSize_)*8/1000.0/10 $ns flush-trace #关闭档案 close $nd close $f0 #使用awk分析记录文件以观察队列的变化 exec awk BEGIN highest_packet_id = -1;packet_count = 0;q_eln = 0; action = $1; time = $2; src_node = $3; dst_node = $4; type =
30、$5; flow_id = $8; seq_no = $11; packet_id = $12; if (src_node = 0 & dst_node = 1) if (packet_id highest_packet_id) highest_packet_id = packet_id; if (action = +) q_len+;print time, q_len;if (action = - | action = d) q_eln = q_len-;print time, q_len; out-$par1.tr queue_length-$par1.tr exit 0#定义一个记录的程
31、序#每格0.01秒就去记录当时的cwndproc record global ns tcp f0set now $ns nowputs $f0 $now $tcp set cwnd_$ns at expr $now+0.01 record#产生传送节点,路由器r1,r2和接收节点set r0 $ns nodeset r1 $ns nodeset n0 $ns nodeset n1 $ns node#建立链路$ns duplex-link $n0 $r0 10Mb 1ms DropTail$ns duplex-link $r0 $r1 1Mb 4ms DropTail$ns duplex-lin
32、k $r1 $n1 10Mb 1ms DropTail#设定队列长度为15个封包大小set buffer_size 15$ns queue-limit $r0 $r1 $buffer_size#根据使用者的设定,指定TCP版本if $par1=Reno set tcp new Agent/TCP/Renoset tcpsink new Agent/TCPSink$tcp set debug_ 0 elseif $par1=Newreno set tcp new Agent/TCP/Newrenoset tcpsink new Agent/TCPSink$tcp set debug_ 0 els
33、e set tcp new Agent/TCP/Sack1set tcpsink new Agent/TCPSink/Sack1$tcp set debug_ 1$ns attach-agent $n0 $tcp#将awnd的值设为24,这是advertised window的上限# advertised window是接收端的缓冲区可以容纳的封包个数,#因此当congestion window的值超过advertised window时,#TCP的传送端会执行流量控制以避免送的太快而导致接收端的缓冲区溢满。$tcp set window_ 24$ns attach-agent $n1 $tc
34、psink$ns connect $tcp $tcpsink#建立FTP应用程序set ftp new Application/FTP$ftp attach-agent $tcp#在0.0秒时,开始传送$ns at 0.0 $ftp start#在10.0秒时,结束传送$ns at 10.0 $ftp stop#在0.0秒时去呼叫record来记录TCP的cwnd变化情况$ns at 0.0 record#在第10.0秒时去呼叫finish来结束模拟$ns at 10.0 finish#计算在传输路径上大约可以容纳多少的封包#计算方式:在bottleneck link上每秒可以传送的封包数*R
35、TT+队列缓冲区大小puts format on path: %.2f packets expr (1000000/(8*($tcp set packetSize_+40) * (1+4+1) * 2 * 0.001) + $buffer_size#执行模拟$ns run附录CTCPv3代码# 产生一个仿真的对象set ns new Simulator#开启一个trace file,用来记录封包传送的过程set nd open out13_1.tr w$ns trace-all $nd#开启两个档案用来记录cwnd变化情况set f0 open cwnd0.tr wset f1 open cw
36、nd1.tr w#定义一个结束的程序proc finish global ns nd f0 tcp0 f1 tcp1 #puts ACK number: $tcp0 set ack_ puts format average throughput: %.1f Kbps expr $tcp1 set ack_*($tcp1 set packetSize_)*8/1000.0/10puts format average throughput: %.1f Kbps expr $tcp0 set ack_*($tcp0 set packetSize_)*8/1000.0/10 $ns flush-tra
37、ce #关闭档案 close $nd close $f0 close $f1 #使用awk分析记录文件以观察队列的变化 exec awk BEGIN highest_packet_id = -1;packet_count = 0;q_eln = 0; action = $1; time = $2; src_node = $3; dst_node = $4; type = $5; flow_id = $8; seq_no = $11; packet_id = $12; if (src_node = 0 & dst_node = 1) if (packet_id highest_packet_id
38、) highest_packet_id = packet_id; if (action = +) q_len+;print time, q_len;if (action = - | action = d) q_eln = q_len-;print time, q_len; out13_1.tr queue_length-13_1.tr exit 0#定义一个记录的程序#每格0.01秒就去记录当时的cwndproc record global ns tcp0 f0 tcp1 f1set now $ns nowputs $f0 $now $tcp0 set cwnd_puts $f1 $now $
39、tcp1 set cwnd_$ns at expr $now+0.01 record#建立节点set r0 $ns nodeset r1 $ns nodeset n0 $ns nodeset n1 $ns nodeset n2 $ns nodeset n3 $ns node#建立链路$ns duplex-link $n0 $r0 10Mb 1ms DropTail$ns duplex-link $n2 $r0 10Mb 1ms DropTail$ns duplex-link $r0 $r1 1Mb 20ms DropTail$ns duplex-link $r1 $n1 10Mb 1ms Dr
40、opTail$ns duplex-link $r1 $n3 10Mb 1ms DropTailset buffer_size 15$ns queue-limit $r0 $r1 $buffer_size#建立TCP Vegas的FTP联机set tcp0 new Agent/TCP/Vegas$tcp0 set v_alpha_ 1$tcp0 set v_beta_ 3$tcp0 set window_ 24$ns attach-agent $n0 $tcp0set tcp0sink new Agent/TCPSink$ns attach-agent $n1 $tcp0sink$ns connect $tcp0 $tcp0sinkset ftp0 new Application/FTP$ftp0 attach-agent $tcp0#建立另一条TCP Vegas的FTP联机set tcp1 new Agent/TCP/Vegas$tcp1 set v_alpha_ 1$tcp1 set v_beta_