3.5 面向连接的运输:TCP
3.5.1 TCP连接
可靠的、按序的字节流
流水线机制,TCP拥塞控制和流量控制机制
在发送方与接收方都有缓存
面向连接的(connection-oriented),通信双方在发送数据之前,需要先相互“握手”(建立连接),即互相发送某些预备报文段以确保数据传输的参数。TCP协议只在端系统中运行,所以中间的网络元素不会维持TCP连接状态。
全双工服务(full-duplex service),同一条TCP连接中可以传输双向数据流。
点对点(point-to-point),TCP连接是在单个发送方与单个接收方之间的连接。
TCP连接的组成包括:连接的两台主机上的缓存、变量和与进程连接的套接字。
3.5.2 TCP报文段结构
3.5.2.1 序号和确认号(ACKs)
一个报文段的序号(segment)是该报文段第一个字节的字节流编号。
建立TCP连接时,双方随机选择序列号。
主机A填充进报文段的确认号(ACKs)是主机A期望从主机B收到的下一字节的序号。
TCP提供累计确认(cummulative acknowledgment),即该序列号之前的所有字节均被正确接收。
当主机从一条TCP连接中收到失序报文段时,由TCP的实现者做出决策(TCP的RFC并未对此明确规定任何规则)
3.5.3 往返时间的估计与超时
超时间隔:过短,引起不必要的重传;过长,对段丢失反应慢。
3.5.3.1 估计往返时间(RTT)
样本RTT(SampleRTT):从某报文段被发出(即交给IP)到对该报文段的确认被收到之间的时间量。
TCP仅为传输过一次的报文段测量SampleRTT,即不为已被重传的文段计算SampleRTT。
TCP维持一个SampleRTT的均值(称为EstimatedRTT),每获得一个新SampleRTT,据以下公式更新:(其中\(\alpha\)的推荐值为0.125)
EstimatedRTT是SampleRTT的加权平均值,这种平均被称为指数加权移动平均(EWMA)
定义RTT偏差DevRTT,用于估算SampleRTT与EstimatedRTT的差值,是它们差值的EWMA。(其中\(\beta\)的推荐值为0.25)
3.5.3.2 设置和管理重传超时间隔
推荐TimeoutInterval的初始值为1秒。
3.5.4 可靠数据传输
TCP发送方有3个与发送和重传有关的主要事件:
- 从上层应用程序接收数据。TCP将接收的数据封装在一个报文段中,报文段中的序列号是该报文段第一个数据字节的字节流编号,TCP启动定时器,设置超时时间TimeoutInterval。
- 定时器超时。TCP重传引起超时的报文段,然后重启定时器。
- 收到ACK。如果确认此前未确认的报文段,更新SendBase(最早未被确认的字节的序号),如果窗口中还有未被确认的分组,重新启动定时器。
快速重传(fast retransmit)
TCP的实现中,若发生超时,超时时间间隔将重新设置(加倍)。这迫使发送方延迟重传丢失的分组,从而增加端到端时延。
发送方通常可在超时事件发生之前,通过冗余ACK(duplicate ACK)来检测丢包情况。
如果TCP发送方接收到对相同数据的3个冗余ACK,就认为该数据之后的报文段已经丢失。随后,TCP就会执行快速重传,即在该报文段超时之前重传丢失的报文段。
3.5.5 流量控制
TCP为它的应用程序提供了流量控制服务(flow-control service)以消除发送方使接收方缓存溢出的可能性。流量控制因此是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。
TCP让发送方维护一个称为接收窗口(receive window)的变量,它指示接收方还有多少的可用缓存。
定义RevBuffer为接收方为TCP连接分配的接收缓存的大小
定义LastByteRead为接收方应用程序从缓存读出的数据流的最后一个字节的编号
定义LastByteRevd为从网络中到达的并且已放入接收方接收缓存的数据流中的最后一个字节的编号
由于TCP不允许已分配的缓存溢出:
接收窗口(RcvWindow,rwdn)根据缓存可用空间设置:
开始时,接收方设定rwnd = RevBuffer。
发送方在连接过程中保证:(即将未确认的数据量控制在rwnd内)
当接收方告知发送方rwnd=0时:
TCP规范要求,当接收方的接收缓存已经存满,即rwnd=0时,发送方继续发送只有一个字节数据的报文段。这些报文段被接收方确认。最终缓存开始清空,并且接收方发出的确认报文里将包含一个非0的rwnd。
3.5.6 TCP连接管理
建立连接,即三次握手(three-way handshake):
- 第一步:客户端的TCP向服务器端的TCP发送一个特殊的TCP报文段(即SYN报文段),该报文段不包含应用层数据但首部的标志位SYN=1;另外,客户端随机选择一个初始序号client_isn,将其置于SYN报文段的序号字段中;该报文段随后被封装在一个IP数据报中。
- 第二步:服务器端从接收到的IP数据报中提取SYN报文段,为该TCP连接分配缓存和变量,并向客户端TCP发送允许连接的报文段(即SYNACK报文段),该报文段不包含应用层数据但首部的标志位SYN=1,确认号字段=client_isn+1,并随机选择初始序列号server_isn置于序号字段。
- 第三步:客户端收到SYNACK报文段后,为该TCP连接分配缓存和变量,再次向服务器发送一个报文段,其确认字段=server_isn+1,SYN=0,并且可以在报文段负载中携带客户端到服务器端的数据。
终止连接:参与一条TCP连接的两个进程中的任何一个都能够终止该连接。举例:
- 客户应用进程发出一个关闭连接命令,这引起客户TCP向服务器发送一个特殊的报文段,其首部的标志位FIN=1。
- 当服务器接收到该报文段后,就向发送方回送一个确认报文段。
- 然后服务器发送它的终止报文段,其中FIN=1。
- 最后客户对该报文段进行确认。此时,在两台主机上用于该连接的所有资源都被释放了。
3.6 控制拥塞原理
拥塞的表现:
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
3.6.1 拥塞原因与代价
情况1:两个发送方和一台具有无穷大缓存的路由器
两台主机A和B都有一条连接,且这两条连接共享源与目的地之间的单跳路由。
假设主机A和B向路由器提供流量的速率是\(\lambda_{in}\)字节/秒。来自主机A和B的分组通过一台路由器,在一段容量为R的共享式输出链路上传输。
无穷大缓存意味着没有重传。由于两条连接共享链路容量,因此接收方的吞吐量上限为R/2。当\(\lambda_{in}\)<=R/2时,\(\lambda_{out}\)=\(\lambda_{in}\)。
当发送方的发送速率接近R/2时,平均时延会越来越大;当超过R/2时,路由器的平均排队分组数会无限增加,平均时延变成无穷大。
拥塞网络的一种代价:当分组的到达速率接近链路容量时,分组经历巨大的排队时延。
情况2:两个发送方和一台具有有限缓存的路由器
假设运输层向网络中发送报文段(含有初始数据或重传数据)的速率用\(\lambda_{in}^{'}\)表示。\(\lambda_{in}^{'}\)有时被称为网络的供给载荷(offered load)
在情况2,实现性能强烈地依赖于重传的方式。
情况2.1,发送方仅当路由器缓存空闲时才发送分组。在这种情况下,不会产生丢包,\(\lambda_{out}\)=\(\lambda_{in}\)=\(\lambda_{in}^{'}\)
情况2.2,发送方仅当确认一个分组已经丢失时才重传。\(\lambda_{out}\)<\(\lambda_{in}^{'}\)
发送方必须执行重传以补偿因为缓存溢出而丢弃(丢失)的分组
情况2.3,发送方可能提前发生超时并重传队列中已被推迟但还未丢失的分组。分组丢失和超时都需要重传,\(\lambda_{in}^{'}\)更大了。
发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本。
情况3:4个发送方和具有有限缓存的多台路由器及多跳路径
两条连接上的流量在路由器上为有限缓存竞争,若一条连接上的供给载荷远小于另一条时,该连接通过路由器的流量会较小。
当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了。
3.6.2 拥塞控制方法
端到端拥塞控制:
- 网络层没有为运输层拥塞控制提供显示支持。
- 端系统通过观察网络行为(如分组丢失和时延)推断拥塞是否发生。
- TCP采取该方法。
网络辅助的拥塞控制:
- 路由器向发送方提供关于网络中拥塞状态的显式反馈信息。
- 可以用简单的一个比特来提供拥塞指示,而这种方法被IBM SNA,DECbit,TCP/IP ECN,ATM等体系结构采用。
- 也可以有更复杂的网络反馈,例如在ATM可用比特率拥塞控制中,反馈路由器在输出链路上支持的最大主机发送速率。
网络辅助的拥塞控制,拥塞信息反馈的两种方式:
- 网络路由器发给发送方直接反馈信息,通常是阻塞分组(choke packet)。
- 路由器标记或更新从发送方流向接收方的分组中的某个字段来指示拥塞。
3.7 TCP拥塞控制
1、发送方如何限制向其连接发送流量:
运行在发送方的TCP拥塞控制机制跟踪一个变量,拥塞窗口(congestion window,cwnd),对发送速率进行限制:
假设接收窗口rwnd足够大,并且丢包和发送时延忽略不计,那么发送方的发送速率大概是cwnd/RTT 字节/秒。通过调节cwnd的值即可控制发送速率。
2、发送方如何感知路径上存在拥塞:
发送方出现了丢包事件(超时或收到3个来自接收方的冗余ACK),发送方就认为出现了拥塞。
3、采用何种算法来改变其发送速率:
若确认以慢速率到达,拥塞窗口以慢速率增加;以高速率到达则以高速率增加。
TCP使用确认来触发增大拥塞窗口,因此被称为自计时(self-clocking)的
TCP拥塞控制算法:
1、加性增、乘性减(Additive-Increase,Multiplicative-Decrease,AIMD)
原理:逐渐增加发送速率,谨慎探测可用带宽,直到发生loss(丢包事件)
加性增(Additive Increase):每个RTT将cwnd增大一个MSS——拥塞避免
乘性减(Multiplicative Decrease):发生loss后将cwnd减半
2、慢启动
当一条TCP连接刚建立时,cwnd通常初始置为一个MSS的较小值,初始发送速率约为MSS/RTT。
由于可用带宽可能远远高于初始速率,希望cwnd能够快速增长。
cwnd的值以1MSS开始,每当传输的报文段首次被确认(收到ACK)就增加1MSS。于是每过1个RTT,cwnd就翻倍,发送速率也就翻倍。即cwnd指数增长。
当发生loss(丢包事件),将ssthresh(慢启动阈值)设置为cwnd/2。
当cwnd=ssthresh(慢启动阈值)时结束这样的指数增长。
loss事件的处理:
- 3个冗余ACK:cwnd变成ssthresh/2,即上次遇到拥塞的值的一半。每过一个RTT,cwnd增加1MSS,即线性增长。
- 超时事件:将cwnd设为1,并重新开始慢启动,
- 3个冗余ACKs表示网络还能够传输一些 segments,timeout事件表明拥塞更为严重
TCP性能分析
求一个TCP连接的平均吞吐量(即平均速率),忽略较短的慢启动阶段。
假定发生超时时cwnd的大小为W,吞吐率是W/RTT
超时后,cwnd=W/2,吞吐率是W/2RTT
平均吞吐率为:0.75W/RTT
吞吐率与丢包率(loss rate,L)的关系:
CongWin从W/2增加至W时出现第一个丢包,那么一共发送的分组数为:
\(W/2+(W/2+1)+(W/2+2)+….+W = 3W^2/8+3W/4\)
W很大时,\(3W^2/8>>3W/4\),因此\(L \approx 8/(3W^2)\)
3.7.1 公平性
TCP:如果K个TCP连接共享相同的瓶颈带宽R,那么每个连接的平均速率为R/K。TCP是公平的。
UDP:多媒体应用通常不使用TCP,以免被拥塞控制机制限制速率。使用UDP的话可以以恒定速率发送,能够容忍丢失,于是产生了不公平。
并发TCP连接:某些应用会打开多个并发连接,如Web浏览器,于是产生公平性问题。
例:链路速率为R,已有9个连接,若新来的应用请求1个TCP,获得R/10的速率;若新来的应用请求9个TCP,获得R/2的速率