TCP/IP 详解卷一 - TCP的定时器和拥塞控制

        TCP 是提供可靠的传输层,它使用的方法之一就是确认从另一端收到的数据。但是数据和确认都可能会丢失。TCP 通过在发送时设置一个定时器来解决这个问题。如果当定时器溢出时还没收到确认,它就会重传该数据。关键在于超时和重传策略,即怎样决定超时的时间间隔和如何确定重传的频率。

        对于每个连接,TCP 管理着四个不同的定时器:重传定时器、坚持定时器、保活定时器 以及  2MSL 定时器。

 

重传定时器

        为了防止丢失数据报文段或确认报文段,当 TCP 发送报文段时,启动了特定报文段的重传计时器,若在计时器超时之前收到对报文段的确认,则撤销计时器。若收到特定报文段的确认之前计时器已经超时,则重传该报文,并把计时器复位。这里最重要的是超时的时间计算,有关该时间的请查阅具体的算法,这里不再进行记录。

 

坚持定时器

        坚持定时器主要是解决零窗口大小通知可能导致的死锁问题。刚开始接收端向发送端发送了一个零窗口报文段。在不久之后,如果接收端的缓存区有一定的空间可以接收数据,此时接收端就会向发送端发送了一个非零窗口大小的报文段(即窗口更新),但是这个非零窗口大小的报文段在传输过程中丢失,导致发送端无法接收到该非零窗口大小的报文段。因此,发送端就会一直处于等待非零窗口大小的报文端通知,由于接收端已经发送了非零窗口大小的报文段,而且并不知道该报文段在传输过程中丢失,则接收端会一直处于等待接收数据状态,如果没有任何措施的话,这个死锁的局面会一直延续下去。

        为了解决上面这个问题,TCP为每一个连接设有一个坚持定时器(也叫持续计数器)。当发送端收到零窗口的确认时,就启动坚持计时器当坚持计时器截止期到时,发送端就发送一个特殊的报文段,叫探测报文段,这个报文段只有一个字节的数据。探测报文段有序号,但序号永远不需要确认,甚至在计算对其他部分数据的确认时这个序号也被忽略。探测报文段提醒接收端,确认已丢失,必须重传。

        坚持计时器的截止期设置为重传时间的值,但若没有收到来自接收端的响应,则发送另一个探测报文段,并将坚持计时器的值加倍和并复位,发送端继续发送探测报文段,将坚持计时器的值加倍和复位,直到这个值增大到阈值为止(通常为 60 秒)。在此之后,发送端每隔 60s 就发送一个报文段,直到窗口重新打开为止。

        坚持定时器的原理:当TCP 服务器收到了客户端的 0 滑动窗口报文时,启动一个定时器来计时,并在定时器溢出时向客户端查询窗口是否已经增大,如果得到非零的窗口就重新开始发送数据,如果得到零窗口就再开一个新的定时器准备下一次查询。

 

保活定时器

        保活定时器是为了应对TCP 连接双方出现长时间的没有数据传输的情况。如果客户端与服务器建立了 TCP连接之后,客户端由于某种原因导致主机故障,则服务器就不能收到来自客户端的数据,而服务器不可能一直处于等待状态,保活定时器就是用来解决这个问题的。服务器每收到一次客户端的数据,就重新设置保活定时器,通常为2 小时,如果 2 小时没有收到客户端的数据,服务端就发送一个探测报文,以后每隔75秒发送一次,如果连续发送10次探测报文段后仍没有收到客户端的响应,服务器就认为客户端出现了故障,就可以终止这个连接。

 

2MSL 定时器

        2MSL 定时器主要是解决以下两种情况:

1.        TIME_WAIT 确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到 ACK,就会触发被动端重发 FIN。因为最后一次确认应答 ACK 报文段很有可能丢失,因而使被动关闭方处于在LIST_ACK 状态的,此时被动关闭方会重发这个 FIN+ACK 报文段,在这等待的 2MSL 时间内主动关闭方重新收到这个被动关闭方重发的 FIN+ACK 报文段,因此,主动关闭方会重新发送确认应答信息,从而重新启动 2MSL 计时器,直到通信双方都进入 CLOSED 状态。如果主动关闭方在 TIME_WAIT 状态不等待一段时间就直接释放连接并进入 CLOSED 状态,那么主动关闭方无法收到来自被动关闭方重发的 FIN+ACK 报文段,也就不会再发送一次确认 ACK 报文段,因此被动关闭方就无法正常进入CLOSED 状态。

2.        有足够的时间让这个连接不会跟后面的连接混在一起。防止已失效的请求连接出现在本连接中。在连接处于 2MSL 等待时,任何迟到的报文段将被丢弃,因为处于 2MSL等待的、由该插口(插口是IP和端口对的意思,socket)定义的连接在这段时间内将不能被再用,这样就可以使下一个新的连接中不会出现这种旧的连接之前延迟的报文段。

TCP的拥塞控制

        TCP 拥塞控制能够提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。拥塞控制主要有几种:慢启动、拥塞避免、快速重传 以及快速恢复。

        拥塞控制的最终受控变量是发送端向网络一次连续写入的数据量(即收到其中第一个数据的确认应答之前的所有数据),称为发送窗口(send window,SWND)。但是发送端往往最终以 TCP 报文段来发送数据,所以 SWND 限定了发送端能够连续发送 TCP 报文段的数量。发送端应该合理的选择 SWND 的大小,若该值太小,会引起网络延迟,若太大,则容易导致网络拥塞。前面中我们知道,接收端可通过其接收通告窗口(RWND)来控制发送端的 SWND 大小,但是发送端应该引入一个拥塞窗口(Congestion Window,CWND)的状态量。实际的 SWND 值就是 RWND 和 CWND 中的较小者。


慢启动

       为了防止网络拥塞,TCP 采用了一种慢启动算法,对发送数据量进行控制。为了调节发送端的数据发送量,引入了拥塞窗口,在慢启动时,将这个拥塞窗口设为 1 个报文段发送数据,之后每收到一次确认应答,拥塞窗口的值就加 1 个报文段。在发送数据包时,将拥塞窗口的大小与接收端主机通知的窗口大小进行比较,然后选择较小的值来控制数据量的发送。拥塞窗口是发送端使用的流量控制,而通告窗口则是接收端使用的流量控制。

       慢启动算法步骤如下(cwnd全称CongestionWindow):

初始化 cwnd = 1,表示可以传一个 MSS 大小的数据;

每当收到一个 ACK,cwnd++,即增加1,呈线性上升;

每当过了一个 RTT,cwnd = cwnd*2,呈指数让升;

 ssthresh(slow startthreshold),是一个上限,当 cwnd >= ssthresh 时,就会进入“拥塞避免算法”。

拥塞避免

       拥塞避免算法是让拥塞窗口缓慢地增大,收到每一轮的确认后,将拥塞窗口的值加1,而不是加倍,这样拥塞窗口的值按照线性规律缓慢增长。在慢启动中,当cwnd >= ssthresh时,就会进入“拥塞避免算法”。一般来说ssthresh的值是65535,单位是字节,当cwnd达到这个值时后,算法如下:

收到一个 ACK 时,cwnd = cwnd + 1/cwnd;

当每过一个RTT时,cwnd = cwnd + 1;



快速重传与快速恢复

        快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(重复发送对前面有序部分的确认),而不是等待自己发送数据时才进行捎带确认,也不是累积收到的报文发送累积确认,如果发送方连续收到三个重复确认,就应该立即重传对方未收到的报文段(有收到重复确认,说明后面的报文段都送达了,只有中间丢失的报文段没送达)。

         快恢复算法与快重传算法配合使用:

当发送方连续收到三个重复确认时,就把慢启动门限 ssthresh 设置为当前拥塞窗口 cwnd 的一半。重传丢失的报文段。设置 cwnd 为 ssthresh 加上3倍的报文段大小;

每次收到另一个重复的 ACK 时,cwnd 增加 1 个报文段大小并发送 1 个分组;

当下一个确认新数据的 ACK 达到时,设置 cwnd 为 ssthresh(跟第 1 步一样设置方法)。这个 ACK 应该是在进行重传之后的一个往返时间内对步骤 1 中重传的确认。另外,这个 ACK 也应该是对丢失的分组和收到的第一个重复的 ACK 之间的所以中间报文段的确认。这一步采用的是拥塞避免算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值