在虚拟机上安装NS2过程中遇到无数问题,现在将我大致的过程列举如下:
sudo apt-get update #更新源列表
sudo apt-get upgrade #更新已经安装的包
sudo apt-get dist-upgrade #更新软件,升级系统
sudo apt-get install build-essential
sudo apt-get install tcl8.5 tcl8.5-dev tk8.5 tk8.5-dev #for tcl and tk
sudo apt-get install libxmu-dev libxmu-headers #for nam
步骤三:下载安装包并编译安装(ns2.35)
tar xvfz ns-allinone-2.35.tar.gz #这个可以图形化操作
cd ns-allinone-2.35 #这个可以图形化操作
./install #进行安装
报错情况:
linkstate/ls.h:137:20: note: use ‘this->erase’ instead
make: *** [linkstate/ls.o] Error 1
Ns make failed!
修改ls文件,位置是:ns-2.35/linkstate/ls.h
第137行
void eraseAll() { erase(baseMap::begin(), baseMap::end()); }
改为:void eraseAll() { this->erase(baseMap::begin(), baseMap::end()); }
保存后,重新然后执行 ./install #重新安装顺利完成
步骤四:配置环境变量
修改当前用户环境变量(对应的文件为’/home/用户名’中的.bashrc,并非’/ns-allinone-2.35’底下的空白.bashrc),重新打开终端即可;
gedit ~/.bashrc # ~ 这个符号为当前用户根目录,即/home/用户名
直接在文档的最后面加上以下环境变量(把用户名改成你的就行):
(注意:你在第一步更新tk和tcl时,版本如果是8.15.19或者其他版本,请替换以下中8.5.10为你的版本号)
export NS_HOME=/home/用户名/ns-allinone-2.35
export PATH=$PATH:$NS_HOME/bin:$NS_HOME/tcl8.5.10/unix:$NS_HOME/tk8.5.10/unix
export LD_LIBRARY_PATH=$NS_HOME/otcl-1.14:$NS_HOME/lib
export TCL_LIBRARY=$NS_HOME/tcl8.5.10/library
步骤五:验证ns是否安装成功
关闭终端,重启终端,输入ns,出现%,说明ns2安装成功
注意:环境变量配错的话,会提示“程序“ns”尚未安装。 此时请不要使用以下命令安装:
sudo apt-get install ns2
应该继续在步骤4中修改环境变量!
步骤六:测试ns并验证nam是否安装成功
1、重新打开一个终端
cd ns-allinone-2.35/ns-2.35/tcl/ex/
ns simple.tcl
倘若弹出动画演示框,则证明ns完全安装正确,下面的问题也不需要看了,至此结束。
倘若提示nam没有安装(Ubutnu16.04没有出现这个问题),执行以下命令
cd ns-allinone-2.35/nam-1.15 #进入nam目录
./configure --with-tcl-ver=8.5 #重新配置
make #重新编译源码
make install #重新安装
命令行输入nam弹出nam console说明nam安装成功,会出现一个图形界面。
参考链接:https://blog.csdn.net/circle2015/article/details/52490582
一、实验目的:
学习TCP的拥塞控制机制并了解TCP Tahoe和TCP Reno协议的运行机制。
实验背景知识:
TCP基于窗口的拥塞控制策略
1.1 加法增加乘法减少(AIMD)窗口算法
TCP是Internet中最流行的端到端传输协议,为主机之间提供可靠按序的传输服务。在现有的TCP/IP协议体系下,TCP拥塞控制机制主要基于加法增加乘法减少(AIMD)算法。在该算法中主要用到三个窗口变量:
(1)拥塞窗口(cwnd):限定源端在拥塞控制中在一定时间内允许传送的最大数据量,是来自源端的流量控制。
(2)通告窗口(awnd):连接建立及传输过程中,接收端向源端通告的最大可接收速率,是来自接收端的流量控制。
(3)有效窗口(win):源端数据发送的实际窗口大小,限定为win=min(cwnd,awnd)。
由于计算机计算能力和存储能力的提高,通告窗口一般都比较大,因此当前发送窗口的大小大多数情况下等于拥塞窗口的大小。
AIMD的具体工作过程为:
(1)源端每收到一个ACK,拥塞窗口按下式增加:
Incr=MSS×(MSS/cwnd) (MSS为分组大小)
cwnd=cwnd+Incr
也就是,如果每个发出的分组都在最近的RTT(往返时延)时间内获得确认,源端就将cwnd增加1,即加法增加。
(2)当发生超时,TCP将超时看作拥塞的标志,并减小发送速率。每发生一次超时,源端重新计算拥塞窗口值:
cwnd=cwnd/2
也就是,一次超时,拥塞窗口值减为当前值的一半,即乘法减少。
1.2 TCP拥塞控制的四个阶段
a 启动阶段
当连接刚建立或超时时,进入慢启动阶段。
当新建TCP连接时,拥塞窗口(cwnd)被初始化为一个数据包大小。源端按cwnd大小发送数据,每收到一个ACK确认,就增加一个数据包发送量,这样慢启动阶段cwnd随RTT呈指数级增长。
慢启动采用逐渐增大cwnd的方法,可以防止TCP在启动一个连接时向网络发送过多的数据包而造成不必要的数据丢失和网络拥塞,并且它还能够避免采用单纯的AIMD算法造成的吞吐量增加过慢的问题。
为了防止cwnd的无限制增长引起网络拥塞,引入一个状态变量:慢启动阈值ssthresh。
当cwnd 当cwnd>ssthresh时,使用拥塞避免算法,减缓cwnd的增长速度。 b 拥塞避免阶段 当TCP源端发现超时或收到3个相同的ACK确认帧时,即认为网络将发生拥塞,此时进入拥塞避免阶段。 在拥塞避免阶段,慢启动域值ssthresh将被设置为当前cwnd的一半,当发生超时时,cwnd被置为初始值1。此时,如果cwnd c、d 快速重传和快速恢复阶段 在拥塞避免阶段,当数据包超时时,cwnd被置为1,重新进入慢启动阶段,这会导致过大地减小发送窗口尺寸,降低TCP连接的吞吐量。因此,引入了快速重传和快速恢复机制。 在快速重传阶段,当源端收到3个或3个以上重复的ACK时,就判定数据包丢失,同时将ssthresh设置为当前cwnd的一半,并重传丢失的包,进入快速恢复阶段。 在快速恢复阶段,每收到重复的ACK,则cwnd加1;收到非重复ACK时,置cwnd=ssthresh,转入拥塞避免阶段;如果发生超时重传,则置ssthresh为当前cwnd的一半,cwnd=1,重新进入慢启动阶段。 这种方法避免了数据包超时后就重新进入慢启动阶段,提高了TCP连接的吞吐量。 实验步骤: 本实验是为了 观测tahoe 和reno协议的特征。 1、仿真实验的网络结构图 实验网络拓扑结构 和 链路参数配置 (FTP代表端施加恒定的流CBR)
2.TCL程序代码(参见附录lab11.tcl) 3.执行方法和结果($为shell的提示符号) 3.1观察Tahoe版本的congestionwindow的变化情况: Tahoe算法是TCP的早期版本。它的核心思想是:让cwnd以指数增长方式迅速逼进可用信道容量,然后慢慢接近均衡。Tahoe包括3个基本的拥塞控制算法:“慢启动”、“拥塞避免”和“快速重传”。 (1)慢启动:避免了连接建立时突发数据流对网络的冲击。 初始设置cwnd为1,并按指数型方式增长,直至cwnd超过ssthresh。 当cwnd>=ssthresh时,Tahoe进入拥塞避免阶段。 (2)拥塞避免:限制传输过程中无限制的速率增长,避免由此可能导致的拥塞。 cwnd以线性方式增长。 如果发生超时或者连续收到3个重复ACK,Tahoe认为发生了拥塞。 对于超时,置ssthresh为当前拥塞窗口的一半,cwnd=1,转入慢启动。 如果收到3个连续ACK,则Tahoe进入快速重传阶段。 (3)快速重传:根据3个重复的应答报文来判断丢包,减少了超时重传的发生,加快了源端对拥塞的响应,使得拥塞能快速消除。立即重传丢失的分组,同时置ssthresh为当前拥塞窗口的一半,cwnd=1,转入慢启动。 Tahoe算法存在着不足之处:在收到3个重复ACK或在超时的情况下,Tahoe置cwnd为1,然后进入慢启动阶段。这一方面会引起网络的激烈振荡,另一方面大大降低了网络的利用率。 $ns lab11.tcl Tahoe 结果为:average throughput: 946.4kbps 使用gnuplot观察cwnd的变化值: $gnuplot
Gnuplot>set title “Tahoe” Gnuplot>set xlabel “time” Gnuplot>set ylabel “cwnd” Gnuplot>set terminal gif Gnuplot>set output “cwnd-Tahoe.gif” Gnuplot>plot “cwnd-Tahoe.tr” with linespoints 1 之后打开cwnd-Tahoe.gif图片如图1所示:
初始阈值=20,cwnd从1开始慢启动,cwnd大小呈指数增长。 cwnd=20后,进入拥塞避免阶段,cwnd值呈线性增长。 当收到3个冗余ACK或超时,阈值减半=10;cwnd减为1,重新进入慢启动阶段。而后呈现指数增长,直到cwnd=阈值,进入线性增长阶段,直到再次出现收到3个冗余ACK事件。 不断重复循环以上过程。 【结果分析】TCP的Congestion Window 值会呈现周期性重复变化。TCP Tahoe 开始执行时,先由slow-start(SS)开始,cwnd超过ssthresh时进入拥塞避免(CA)阶段。由于传送到网络上的丢包不断增加,当超出允许能传送到网络上的个数时,路由器开始使用DropTail算法将数据报丢掉。当数据报遗失时,TCP Tahoe会将ssthresh设为发现数据报遗失时的一半,接着将Window的值设为1。Tahoe重新进入slow-start阶段。 3、2观察Reno版本的congestion window的变化情况:
针对Tahoe算法的不足之处,1990年Jacobson在Tahoe的基础上提出了改进算法Reno。改进主要有两个方面:一是对于收到连续3个重复ACK,算法不经过慢启动,而直接进入拥塞避免阶段;二是增加了快速重传/快速恢复机制。具体实现过程为: (1)收到三个重复的ACK,进入快速重传/快速恢复,此时ssthresh设置为当前拥塞窗口的一半。 (2)重传丢失的数据包,并置cwnd=cwnd+ndup(ndup为收到的重复ACK数)。 (3)发送新的数据包。 (4)当收到非重复的ACK时,cwnd=ssthresh。 (5)进入拥塞避免阶段。 从上面的过程可以看出,Reno在收到3个重复ACK后,就转入快速重传/快速恢复阶段;而遇到超时时,Reno和Tahoe一样进入慢启动阶段。 $ns lab11.tcl Reno 结果为: average throughput: 948.8kbps
使用gnuplot观察cwnd的变化值: $gnuplot
Gnuplot>set title “Reno” Gnuplot>set xlabel “time” Gnuplot>set ylabel “cwnd” Gnuplot>set terminal gif Gnuplot>set output “cwnd-Reno.gif” Gnuplot>plot “cwnd-Reno.tr” with linespoints 1
之后打开cwnd-Reno.gif图片如图2所示: 【分析】 初始阈值=20,cwnd从1开始进入慢启动阶段,而后cwnd大小呈指数增长。当检测到数据报遗失时,ssthresh和cwnd的值会被设置为先前cwnd值的一半。因此重传遗失数据报后,TCP Reno 会由 Congestion Avoidanc(CA)开始。由于结束Fast recovery 后,TCP Reno中cwnd的值由先前cwnd值的1/2开始增加,所以得到的平均吞吐量比TCP Tahoe 大一些。此外,当TCP的传送端观察到端点到端点的路径没有拥塞的情况下,会持续地以累加的方式增加传送速率。但是,当检测到路径拥塞情况发生时,则以倍数方式减少传送速率。 4.实验分析 通过图1可以看出,在TCP的Tahoe版本中,Congestion Windows值会呈现周期性的重复变化。刚开始采用Slow-Start开始,cwnd呈指数方式增长,当cwnd超过Ssthresh时就进入了Congestion Avoidance阶段。由于网络上的数据包不断增加,超过路由器的转发能力时,排队缓冲队列出现了溢出,路由器开始使用Drop-tail将数据包丢掉。当数据包丢失后,Tahoe版本TCP将ssthresh设为出现数据包丢失时的Windows值的1/2,并将cwnd值重设为1,并重新开始执行Slow-Start算法。 通过图2可以看出,在TCP的Reno版本中,开始阶段与Tahoe的表现一样。当网络上的数据包不断增加,超过路由器的转发能力时,排队缓冲队列出现了溢出,路由器开始使用Drop-tail将数据包后,Reno版本TCP将ssthresh和cwnd都设为出现数据包丢失时的Windows值的1/2,并开始执行Congestion Avoidance算法。 从以上分析可以看出Tahoe版本的TCP在每次出现封包丢失的时候都重新开始执行Slow-Start算法,这样使得网络的吞吐率并不高。但经过改进后的Reno版本出现封包丢失的时候,并不是把当前cwnd设为1,而是设为出现封包丢失时的1/2,所以Reno版本的TCP的平均吞吐率较Tahoe更高,这一点可以从实验结果得证。
附录:lab11.tcl(有修改过可正常执行,实验文档上给出的代码有错) if{ $argc !=1 } {
puts "Usage:ns lab11.tcl tcpversion"
exit
}
setpar1 [lindex $argv 0]
setns [new Simulator]
#打开一个trace文件,用来记录数据报传送的过程
setnd [open $par1.tr w]
$nstrace-all $nd
#打开一个文件用来记录cwnd变化情况
setf0 [open cwnd-$par1.tr w]
#定义一个结束的程序
procfinish {} {
global ns nd f0 tcp
puts[format "average throughput:%.1f Kbps" \ [expr [$tcp set ack_]*([$tcpset packetSize_])*8/1000/10]]
$ns flush-trace
close $nd
close $f0
exit 0
}
#定义一个记录的程序
procrecord {} {
global ns tcp f0
set now [$ns now]
puts $f0 "$now [$tcp set cwnd_]"
$ns at [expr $now+0.01] "record"
}
#产生传送结点,路由器r1和r2和接收结点
setn0 [$ns node]
setr0 [$ns node]
setr1 [$ns node]
setn1 [$ns node]
#建立链路
$nsduplex-link $n0 $r0 20Mb 1ms DropTail
$nsduplex-link $r0 $r1 1Mb 4ms DropTail
$nsduplex-link $r1 $n1 20Mb 1ms DropTail
#设置队列长度为18个封包大小
setqueue 18
$nsqueue-limit $r0 $r1 $queue
#根据用户的设置,指定TCP版本,并建立相应的Agent
if { $par1 == "Tahoe" } {
set tcp [new Agent/TCP]
set tcpsink [new Agent/TCPSink]
}elseif { $par1 == "Reno" } {
set tcp [new Agent/TCP/Reno]
set tcpsink [new Agent/TCPSink]
}
$nsattach-agent $n0 $tcp
$nsattach-agent $n1 $tcpsink
$nsconnect $tcp $tcpsink
#建立FTP应用程序
setftp [new Application/FTP]
$ftpattach-agent $tcp
$nsat 0.0 "$ftp start"
$nsat 10.0 "$ftp stop"
#在0.0s时调用record来记录TCP的cwnd变化情况
$nsat 0.0 "record"
$nsat 10.0 "finish"
$nsrun