TCP 梳理总结
TCP提供面向连接、可靠的字节流服务。
TCP重点关注的几个问题:
连接维护
顺序问题
丢包问题
流量控制(协调发送者与接收者的速度)
拥塞控制(协调适应外部网络环境)
连接维护
三次握手、四次挥手,上图是状态变迁图。
为什么是三次握手,而不是两次:一般有去有回才认为是通的,另外发起端A主动打开发起syn后,B未响应,A会重试,若2次握手即建立连接,则重试的syn请求过段时间,B收到后,B应答了,会造成建立多条TCP连接(实际A只想建立一条)。
A发起fin并收到ack后,此时为半关闭状态。
为什么TIME_WAIT状态后需要等待2MSL(max segment lifetime报文最大生存时间): B可能未收到最后这个ack,B就会重发FIN,这时候若A未等待2msl,这时候端口会释放可能被另外一个程序占用,此时另外一个程序收到FIN可能会引起混乱(虽然有seq顺序的保证)。若超过2msl,还收到FIN,会回RST直接断开连接。
顺序问题
通过seq来保证顺序
起始序号是在三次握手中确定的,32位,每4微妙加1,循环一轮需要四个多小时(ip头部中有8位的生存时间TTL,超过后就不会再转发,所以不会存在4个小时的包还存活着)
为什么起始序号不是从1开始:A给B发送1、2两个数据包,由于不稳定,A重发了几次,然后A断开连接后又重新建立了连接,此时A又发送了1数据包,这时候上一个连接的2数据包兜兜转转又被B接收到了,造成了混乱
丢包问题
seq序列号及重传机制。
超时重传: 对于发送的每一个包,但未收到ack的,会设置一个定时器,超过的就会重传。超时时间问题(估算往返时间,采样RTT,进行加权计算。 每当遇到一次超时重传,都会将下一次超时时间间隔设置为之前的2倍)
快速重传: 当接收方发现包丢失时(如收到1、3数据包,2未收到),会发送冗余的ACK期望的包序列(收到1,下一个是2),发送方收到后3个重复ack,不管超时时间立即重发。
流量控制
滑动窗口(receiver`s advertised window. rwnd). 避免发送者发送过快接收者处理不过来。
发送端的数据结构:
已发送已确认,已发送未确认,未发送可以发送,未发送不可发送
其中滑动窗口=已发送未确认 + 未发送可以发送的.
当收到4的确认时,窗口会向右滑动一格。
接收端的数据结构:
接收已确认的(应用程序还未读取),还没接收马上能接收的,不能接收的。
滑动窗口=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead) (红色这部分)。
当应用一直不读取数据时,随着NextByteExpected变大,滑动窗口会逐步变小,直到0,此时发送端不能发送数据。发送端会定时探测,看滑动窗口是否有变大。
低能窗口综合征: 避免接收端窗口变大一点后就发送填满,又导致等待,而是等窗口到一定的大小。
拥塞控制
拥塞窗口(congestion windon-cwnd).避免发送者发送太快,网络处理不过来。尽量占满带宽。
(LastByteSent - LastByteAcked)(发送窗口) <= min {cwnd, rwnd}
拥塞控制避免包丢失及超时重传,一旦出现此现象,说明发送太快了。(以丢包未依据,BBR以探测带宽未依据)
慢启动: TCP 连接开始,cwnd=1,一次只能发送一个;当收到这一个确认的时候,cwnd 加一,于是一次能够发送两个;当这两个的确认到来的时候, cwnd 加二,于是一次能够发送四个;这是指数性的增长。
慢启动初始窗口(IW-initial window),从最初的1,现在已经是10
拥塞避免:当cwnd达到ssthresh(slow start threshold慢启动阈值)后,cwnd开始变为线性增长,每收到一个确认后,cwnd 增加 1/cwnd。 然后出现丢包时,将ssthresh设置为cwnd/2,cwnd设置为一个较低值,如下图:
快速恢复: 拥塞避免后出现的丢包会导致cwnd回到解放前,而在快速重传的场景下(收到重复ack意味网络还行),会启动快速恢复策略:
将ssthresh设置为cwnd/2,cwnd设置为ssthresh + 3倍报文段大小;每收到一个重复 ACK,cwnd 增加 1 个 MSS ; 当新数据 ACK 到达后,设置 cwnd 为 ssthresh。线性增长
Google BBR 拥塞控制
从丢包到测量驱动
参考及引用: tcp\ip详解; 趣谈网络协议; Web协议详解与抓包实战
评论