各种TCP版本.docx
《各种TCP版本.docx》由会员分享,可在线阅读,更多相关《各种TCP版本.docx(24页珍藏版)》请在冰豆网上搜索。
各种TCP版本
[zz]各种TCP版本之TCPReno与TCPVegas共存
实验目的
探讨TCPVegas的提出,TCPVegas的内涵,TCPVegas的优越性及其没有在Internet上广泛应用的主要原因。
基础知识回顾
【TCPReno性能分析】
前面,我们了解了TCPTahoe、TCPReno系列及TCPSack的工作原理,通过实验,将各种TCP版本进行了对比。
综合来看,即使源端不通过等待超时来恢复一个窗口数据中丢失的包,Reno和New-Reno在一个RTT(RoundTripTime)内至多也只能重传一个被丢弃的包。
SACK使用“管道”(pipe)变量表示在发送路径上损失的数据包的数量。
Reno优于Tahoe,New-Reno和SACK则优于Tahoe和Reno。
由于SACK不像New-Reno一次全部重传已发送包,而是有选择地重传,因此在一个窗口中出现数据包大量丢失时,SACK的性能优于New-Reno,但SACK的最大缺点在于要修改TCP协议。
其中,Reno是目前应用最广泛且较为成熟的算法。
我们现在对Reno算法做一个简单的性能分析。
优点:
公平性方面,据数据统计,Reno的公平性还是得到了相当的肯定,它能够在较大的网络范围内理想地维持公平性原则。
缺点:
1.从Reno运行机制中很容易看出,为了维持一个动态平衡,必须周期性地产生一定量的丢失;2.AIMD(Additive-Increase,Multiplicative-Decrease,减少快,增长慢)机制限制了Reno的吞吐量;3.在大窗口环境下,由于一个数据包的丢失所带来的窗口缩小要花费很长的时间来恢复。
因此,带宽利用率不可能很高且随着网络的链路带宽不断提升,这种弊端将越来越明显。
基于上述原因,TCPVegas应运而生。
【TCPVegas简介】
Brakmo和Peterson在1995年提出了一种是用RTT测量网络状况的拥塞控制算法,称之为TCPVegas。
首先,我们来解释一下RTT的概念:
RTT(RoundTripTime,回路响应时间)指一个TCP数据包从源端发送到接收端,源端收到接收端确认的时间间隔。
Vegas就是通过观察以前的TCP连接中RTT值的改变情况来控制拥塞窗口cwnd。
如果发现RTT变大,那么Vegas就认为网络发生拥塞,并开始减小cwnd;如果RTT变小,Vegas则解除拥塞,再次增加cwnd。
这样,cwnd在理想情况下就会稳定在一个合适的值上。
这样做的最大好处在于拥塞机制的触发只与RTT的改变有关,而与包的具体传输时延无关。
由于它没有采用包丢失来判断网络可用带宽,而改以用RTT的改变来判断,所以能较好地预测网络带宽使用情况,并且对小缓存的适应性较强,其公平性、效率都较好。
Vegas使用了3个方法以增加传送的吞吐量(throughput)、减少数据包的丢失。
下面分别进行介绍:
1.新的重送机制(NewRetransmissionMechanism)
当一个数据包被目的端接收时,目的端会根据收到的数据包序号返回一个ACK(ackonwledge)表示这个数据包已收到;如果收到非连续的数据包,则返回序号相同的ACK(DuplicateACK,重复ACK)。
TCP会根据数据包被送出及返回的时间计算数据包平均传送时间RTT。
TCP利用两种方法来检测是否有数据包丢失并重送丢失的数据包。
首先,当一个数据包被送出时,TCP记录此数据包被送出的时间,并检查此数据包的ACK是否在某一个时间范围内被送回。
如果没有,则传送端会在超时后重送丢失的数据包。
其次,为了加快重送的速度,若TCP收到n(通常为3)个重复ACK时,TCP就直接将数据包视为已经丢失,不待超时发生便立即重送丢失的数据包。
随即进入FastRetransmit和FastRecovery阶段。
在TCPVegas中,Vegas改进了重送的机制,每当收到一个DuplicateACK时,Vegas会特别留意RTT的值以检查是否有超时发生。
若是,则不需要等待3个DuplicateACK,Vegas就会直接重送此数据包。
此外,当丢失的数据包被重送并返回新的ACK时,Vegas也会特别注意第一个或第二个返回的ACK,以检测随后的数据包是否已超时,并重送丢失的数据包。
2.新的拥塞避免机制(NewCongestionAvoidanceMechanism)
我们已经知道,TCPReno的拥塞控制算法利用数据包丢失作为网络拥塞的信号,为了增加传输效果并探测网络的可用带宽,Reno会持续增加window的大小直到数据包丢失,因此TCPReno会周期性遭遇数据包丢失的问题。
TCPVegas则采用另一种方式来控制传送速率:
通过观察RTT的变化来控制cwnd的大小。
有关TCPVegas的拥塞控制算法简述如下:
Vegas根据预期传送率和实际传送率之间的差异值来调整cwnd的大小。
当Diff的值大于β时,意味着传送速率太快,应该减小cwnd的值以减缓传送的速率。
反之,当Diff的值小于α时,则表明传送速率较慢,应该加大cwnd的值,以增加传送的速率。
其实,从某种角度看,Diff的值就是这个联机路径Bottleneck的队列长度,而Vegas希望能让队列长度维持在α与β之间。
当Diff的值小于α时,表明网络的使用率太低,可以多送一些数据;当Diff的值大于α小于β时,网络的使用率比较稳定,可以恒速发送数据;当Diff的值大于β时,表明网络开始发生拥塞,因此应该减慢传送速度。
3.修改Slow-start阶段(ModifiedSlow-start)
与TCPReno相比,TCPVegas不仅希望能有效地利用可用频宽,而且也尽量避免因为传送太快而发生数据包丢失的情况。
因此在慢开始(Slow-start)阶段,为了检测及避免数据包丢失,TCPVegas减慢了cwnd增加的速度。
Vegas修改了TCP的Slow-start算法:
cwnd的值大约经过2个RTT后才增加1倍。
与TCPReno不同的是,Vegas根据预期传送率与实际传送率之间的差异值(Diff)来调整ssthresh(慢开始门限)的值。
当TCPVegas检测到网络开始有队列产生时,Vegas就由慢开始(Slow-start)进入拥塞避免(CongestionAvoidance)阶段。
【TCPVegas参数设置】
TCPVegas的使用与TCPReno大致相同,只是要另外设置α和β的值(默认情况下,α为1,β为3)。
其设置方法如下所示:
settcp0[newAgent/Vegas]
$nsattach-agent$n0$tcp0
$tcp0setv_alpha_2
$tcp0setv_beta_5
此外,还可以自行设定γ的值。
在NS中,当网络上的队列长度超过γ时,Vegas会由慢开始阶段进入拥塞避免阶段,并将cwnd的值降为原来的7/8(v_gamma的默认值为1)。
【实验步骤】
【实验一:
同构型环境】
我们先假设一个简单的网络环境(同构型环境):
传输层都使用相同的TCP版本。
其中,n0、n1、n2、n3为结点,R0与R1为路由器,各结点与路由器的传输速率均为10Mbps,传输延迟为1ms,路由器间的传输速率是1Mbps,传输延迟是20ms。
代理(Agent)为TCPVegas,应用层(Application)为FTP。
2.TCL程序代码(假设我将此代码保存于/home/ns下的lab19.tcl文件中)
#===================================
#Simulationparameterssetup
#===================================
setval(stop)10.0;#timeofsimulationend
#===================================
#Initialization
#===================================
#产生一个仿真对象
setns[newSimulator]
#定义NAM中数据流的颜色
$nscolor1red
$nscolor2blue
#打开一个路径文件,用来记录数据包传送的过程
setnd[openout19_1.trw]
$nstrace-all$nd
#打开两个文件,记录cwnd变化情况
setf0[opencwnd0.trw]
setf1[opencwnd1.trw]
#打开一个NAM跟踪文件
setnamfile[openout.namw]
$nsnamtrace-all$namfile
#===================================
#Termination
#===================================
#定义一个结束程序
procfinish{}{
globalnsndnamfilef0f1tcp0tcp1
$nsflush-trace
close$nd
close$namfile
close$f0
close$f1
execnamout.nam&
#使用awk分析trace文件以观察队列的变化情况
#exec使得awk文件在finish中直接执行
execawk{
BEGIN{
highest_packet_id=-1;
packet_count=0;
q_len=0;
}
{
action=$1;
time=$2;
src_node=$3;
dst_node=$4;
type=$5;
flow_id=$8;
seq_no=$11;
packet_id=$12;
#如果对象是路由器R1与R2,此序号(2,3)与结点的定义顺序相对应
if(src_node=="2"&&dst_node=="3"){
if(packet_id>highest_packet_id){
highest_packet_id=packet_id;
}
#如果数据包入队,队列长度加1并打印出当时的时间及队列长度
if(action=="+"){
q_len++;
printtime,q_len;
}
#如果数据包出队或被丢弃,队列长度减1并打印当时的时间及队列长度
elseif(action=="-"||action=="d"){
q_len--;
printtime,q_len;
}
}
}
}out19_1.tr>queue_length-19.tr
#将out19_1.tr文件用awk分析后得到的结果存入文件queue_length-19.tr中
exit0
}
#定义一个记录的程序,每隔0.01s去记录当时的cwnd。
此间隔时间可变,其值
#越大,所绘图形约粗糙
procrecord{}{
globalnstcp0f0tcp1f1
setnow[$nsnow]
puts$f0"$now[$tcp0setcwnd_]"
puts$f1"$now[$tcp1setcwnd_]"
$nsat[expr$now+0.01]"record"
}
#===================================
#NodesDefinition
#===================================
#建立结点
setn0[$nsnode]
setn1[$nsnode]
setn2[$nsnode]
setn3[$nsnode]
setn4[$nsnode]
setn5[$nsnode]
#===================================
#LinksDefinition
#===================================
#建立结点间的链接
$nsduplex-link$n0$n210.0Mb1msDropTail
$nsduplex-link$n1$n210.0Mb1msDropTail
$nsduplex-link$n3$n410.0Mb1msDropTail
$nsduplex-link$n3$n510.0Mb1msDropTail
$nsduplex-link$n2$n31.0Mb20msDropTail
#设置最大队列长度为15
setbuffer_size15
$nsqueue-limit$n2$n3$buffer_size
#确定NAM中结点的位置
$nsduplex-link-op$n0$n2orientright-down
$nsduplex-link-op$n1$n2orientright-up
$nsduplex-link-op$n3$n4orientright-up
$nsduplex-link-op$n3$n5orientright-down
$nsduplex-link-op$n2$n3orientright
#===================================
#AgentsDefinition
#===================================
#建立一个TCP/Vegas代理
settcp0[newAgent/TCP/Vegas]
$tcp0setv_alpha_1
$tcp0setv_beta_3
$tcp0setwindow_24
$tcp0setfid_1
$nsattach-agent$n0$tcp0
setsink2[newAgent/TCPSink]
$nsattach-agent$n4$sink2
$nsconnect$tcp0$sink2
#建立另一个TCP/Vegas代理
settcp1[newAgent/TCP/Vegas]
$tcp1setv_alpha_1
$tcp1setv_beta_3
$tcp1setwindow_24
$tcp1setfid_2
$nsattach-agent$n1$tcp1
setsink3[newAgent/TCPSink]
$nsattach-agent$n5$sink3
$nsconnect$tcp1$sink3
#===================================
#ApplicationsDefinition
#===================================
#建立一个TCP/Vegas的FTP联机
setftp0[newApplication/FTP]
$ftp0attach-agent$tcp0
$nsat0.0"$ftp0start"
$nsat10.0"$ftp0stop"
#建立另一个TCP/Vegas的FTP联机
setftp1[newApplication/FTP]
$ftp1attach-agent$tcp1
$nsat5.0"$ftp1start"
$nsat10.0"$ftp1stop"
$nsat0.0"record"
$nsat$val(stop)"$nsnam-end-wireless$val(stop)"
$nsat$val(stop)"finish"
$nsat$val(stop)"puts\"done\";$nshalt"
#执行模拟
$nsrun
3.执行方法
[root@localhosttclfiles]#cd/home/ns
[root@localhostns]#nslab19.tcl
4.执行结果
图22.098s时,数据包传送情况
由代码可见,第一条Vegas从0s开始执行,10s结束。
因此2.098s时,只有红色(代表tcp0)数据包在传输。
下面,我们看一下8s左右数据包的传送情况。
如图3所示:
图38.094s时,数据包传送情况
第二条Vegas从5s开始执行,10s结束。
因此,8.09s时有红色和蓝色(代表tcp1)两种数据包在传输。
5.使用gnuplot观察cwnd的变化值,如图4所示。
其执行方法如下:
[root@localhostns]#gnuplot
gnuplot>settitle"Vegas"
gnuplot>setxlabel"time"
gnuplot>setylabel"cwnd"
gnuplot>plot"cwnd0.tr"withlinespoints1,"cwnd1.tr"withlinespoints2
图4TCPVegas中cwnd变化图
(备注:
红色线条为tcp0的cwnd变化情况,绿色线条为tcp1的cwnd变化情况)
从图中可以看到,在慢开始(Slow-start)阶段,cwnd的值大约经过2个
RTT才会增加1倍。
与Reno不同的是,当Diff的值介于α与β之间时,Vegas的cwnd值会维持在一个稳定的状态,我们可通过分析记录文件来观察队列的变化。
值得注意的是,当有两条以上联机存在于网络时,Vegas还是能维持在稳定的状态而且不会因传送得太快而造成数据包丢失。
因为,基本上Vegas的拥塞控制算法是一种“拥塞避免”方法。
6.使用gnuplot观察queuelength的变化值,如图5所示。
其执行方法如下:
[root@localhostns]#gnuplot
gnuplot>settitle"queuelength"
gnuplot>setxlabel"time"
gnuplot>setylabel"packets"
gnuplot>plot"queue_length-19.tr"withlines2
图5TCPVegas队列长度变化情况
在0s到0.6s间,tcp0发送数据包,队列长度持续增长;0.6s到0.7s,网络发生拥塞,队列长度减小;0.7s到5s,网络稳定,队列长度维持基本不变。
5s后,tcp1也开始发送数据包,使得队列中的数据包数突然激增,于5.8s时网络拥塞。
随之,调整数据包的数目,于6s左右达到了新的平衡。
实验结果显示,在同构型环境下,TCPVegas比TCPReno有更好的吞吐量,更小的丢包率。
【实验2:
异构型环境下TCPVegas与TCPReno的运行】
过上面的实验,我们证明了TCPVegas能较好地预测网络带宽使用情况,其公平性、效率都较好。
但是,为什么它没有在Internet上得到广泛应用呢?
我们提过,TCPReno是目前应用最广泛的算法,因此在使用TCPVegas时,势必需要考虑是否能与TCPReno共存并正常运行。
接下来,以一个简单是例子来说明,当网络中的传输协议不完全都是TCPVegas时(即在异构型的环境下),TCPVegas的运行情况。
1.仿真实验网络结构图(图6)
此结构图与图1基本相同,但有一点不同的在于tcp1为TCPReno,在此就不赘述了。
2.TCL程序代码(假设我将此文件保存于/home/ns/下的lab21.tcl中)
#产生一个仿真对象
setns[newSimulator]
#定义NAM中数据流的颜色
$nscolor1red
$nscolor2blue
#打开一个trace文件记录数据包传送的过程
setnd[openout21.trw]
$nstrace-all$nd
#打开一个NAM跟踪文件
setnf[openout.namw]
$nsnamtrace-all$nf
#打开两个文件记录cwnd变化情况
setf0[opencwnd-vegas.trw]
setf1[opencwnd-reno.trw]
#定义一个结束程序
procfinish{}{
globalnsndf0tcp0f1tcp1nf
#显示最后的平均吞吐量,吞吐量为链路中每秒传送的比特数=收到
#的应答(ACK)数(成功发送的数据包数)*每个数据包的大小(比特#数)/传输时间
puts[format"Vegas-throughput:
%.1fKbps"\
[expr[$tcp0setack_]*([$tcp0setpacketSize_])*8/1000.0/10]]
puts[format"Reno-throughput:
%.2fKbps"\
[expr[$tcp1setack_]*([$tcp1setpacketSize_])*8/1000.0/10]]
$nsflush-trace
close$nd
close$f0
close$f1
close$nf
#执行nam
execnamout.nam&
exit0
}
#定义一个记录文件,每隔0.01s记录当时的cwnd值
procrecord{}{
globalnstcp0f0tcp1f1
setnow[$nsnow]
puts$f0"$now[$tcp0setcwnd_]"
puts$f1"$now[$tcp1setcwnd_]"
$nsat[expr$now+0.01]"record"
}
#建立结点
setr0[$nsnode]
setr1[$nsnode]
setn0[$nsnode]
setn1[$nsnode]
setn2[$nsnode]
setn3[$nsnode]
#建立结点间的链接
$nsduplex-link$n0$r010Mb1msDropTail
$nsduplex-link$n2$r010Mb1msDropTail
$nsduplex-link$r0$r11Mb20msDropTail
$nsduplex-link$r1$n110Mb1msDropTail
$nsduplex-link$r1$n310Mb