TCP协议3
拥塞控制
拥塞控制无外乎:1)在发生拥塞前采取手段避免进入拥塞。2)在发生拥塞后移除。考虑如何在TCP层面做拥塞控制。
TCP通过减小发送窗口的大小来做出响应。发送者窗口受接收者窗口大小和拥塞窗口大小(cwnd)影响。发送数据不应该大于接受者窗口大小和拥塞窗口大小,拥塞窗口大小只有发送者自己知道。所以发送窗口大小应该小于等于其二中最小的。 TCP拥塞控制策略由以下几个阶段组成:
- 慢启动
- 拥塞避免
- 拥塞检测
慢启动阶段:1)首先初始化拥塞窗口大小为1个MSS。2)每接收到一个确认,拥塞窗口大小加1个MSS。3)这个阶段拥塞窗口大小指数增长。
例如,假设A初始化拥塞窗口大小为cwnd=1MSS,发送一个报文段收到确认后,cwnd=2MSS;然后再发送2个报文段,收到两个确认后,cwnd=4MSS;然后再发送4个报文段,收到确认后,cwnd=8MSS......,直到cwnd达到慢启动阈值。 拥塞避免阶段:1)达到阈值之后,cwnd线性增长避免拥塞。2)收到每个确认,cwnd = cwnd + 1MSS。3)这个阶段持续到cwnd达到接收窗口大小。
拥塞检测阶段:根据如何检测到丢失来做出相应处理。
- 检测到超时,在收到确认前已经超时,极大可能是网络拥塞,报文段在网络中丢失。这种情况下,发送方需要:1)将慢启动阈值设置为当前的cwnd的一半。2)将cwnd设置为1个MSS。3)重启慢启动阶段。
- 检测到收到3个重复确认,发送者收到一个报文段的3个重复确认时,发生网络拥塞的几率很小,可能是一个报文段丢失,稍后发送的几个报文段达到。这种情况下,发送方:1)将慢启动阈值设置为当前cwnd的一半。2)将cwnd减到慢启动阈值大小。3)重启拥塞避免阶段。
TCP重传
当连接建立后,传输的数据可能在网络中丢失。TCP主要通过下面两点发现数据丢失:
- 每发送一个报文段时设置一个超时定时器,如果计时器溢出时还没有收到确认,那就应该重传数据。
- 收到3个重复的确认时,TCP假设对应的报文段丢失,立即重传数据不用等待计时器溢出。
假设A发送5个报文段{s1,s2,s3,s4,s5}给B,B在接收s1后发送确认报文段请求发送s2。s2丢失。s3送达,B发现不是s2,继续发送确认报文段请求发送s2,第一次重复。s4送达,B继续发送确认报文段请求发送s2,第二次重复。s5送达,B继续发送确认报文段请求发送s2,第三次重复。A收到了三个对s2重复的确认,认为s2丢失,立即重传不会等待计时器溢出。
需要注意的是,B在收到重传的s2后,并不需要请求发送s3、s4、s5,而是直接请求发送s6。这是因为B接收了它们并回应了确认,虽然是浪费在了请求s2中。
那么要是对于丢失的数据没有收到3个重复的确认,只能等待计时器溢出重传了。
TCP计时器
对于每个连接,TCP使用4个不同定时器。
- Time Out Timer(超时定时器)
- Time Wait Timer(等待定时器)
- Keep Alive Timer(保活定时器)
- Persistent Timer(坚持定时器)
TCP使用超时计时器来重传丢失的数据。如果定时器溢出时还没有收到确认就重传数据并重启定时器。
TCP使用等待计时器来帮助终止连接。如四次挥手那个图,客户端在接收到FIN后发送最终确认ACK,此时启动等待计时器。这样最终确认ACK丢失的话也就可以重传。还可以阻止刚刚未完全关闭的端口被其它应用程序打开。定时器的值通常设置为2倍的TCP报文段寿命。
TCP使用保活计时器来阻止长期闲置的TCP连接。每次服务器从客户端得到回应就重置定时器为2小时;若超过2小时没有响应,则发送10个探针段到客户端,发送间隔75s。发送了10个探针段都没有响应的话,就假设客户端已经关闭了。服务器自动关闭连接。
TCP使用坚持定时器来处理零窗口大小的死锁情况。TCP通过控制窗口大小来进行流量控制,如果窗口大小为0将有效组织对方发送数据,直到窗口变为非0。由于TCP不对不包含数据的ACK报文段进行确认,如果一个确认丢失了,双方就有可能因为等待对方而终止连接。
假设接收方发送了个窗口为0的报文段后,发送方等待。接收方后来发送了窗口非0的报文段,但是丢失了。此时,接收方再等待数据到来,而发送方在等待允许它继续发送数据的窗口更新。防止这种死锁情况发生,发送方在收到接收方发来的窗口为0的通告后启动坚持定时器,如果时间走完就向接收方发送一个探针段询问窗口,接收方回应,如果窗口非0即可发送数据,如果为0,定时器继续循环。
参考
[1] TCP/IP详解卷1
[2] GateVidyalay