重传机制
- 超时重传:超时重传时间(RTO)设定为略大于RTT(动态)。触发场景包括自己发送的数据包丢失和别人给自己的回应数据包丢失。启动重传机制后如果还没有收到数据包,则RTO设置为上次的两倍,直到达到重传次数上限。缺点是周期长。
- 快速重传:接收方没有收到期望的SEQ,就会重复发送同样的ACK。发送方收到同样的ACK达到一定次数,无需等待超时,就会重传。问题是只能重传一个SEQ包,如果连续丢包,效率很低。
- SACK:选择性确认,将已收到的数据的信息发送给发送方。接收方回复,在发送ACK的同时,同时发送SACK告诉发送方在ACK后的哪些报文(区间)我已经接收了。Duplicate SACK,如果发送方因为某些原因发送了重复报文,接收方可以使用SACK来告诉发送方发送重复了。
滑动窗口机制
- 窗口:发一个TCP报文等一个回应太慢,RTT越长,效率越低。接收端告诉发送端自己还有多少缓冲区可以接收数据,发送端就可以无需等待应答一次性发送多个。发送方滑动窗口大小 = 已发送但未收到ACK的数据大小 + 未发送但仍可发送的数据大小。窗口上的数据实际上在操作系统的缓存上。
流量控制
- 定义:通过滑动窗口实现流量控制。接收方的窗口大小会根据操作系统调整大小,然后实时把大小同步给发送方。如果不进行流量控制,接收方处理不过来导致丢包就会触发重发,导致资源浪费。
- 死锁:发送收缩窗口的消息之后,由于收缩的消息不能立即到达,操作系统不能立即减小缓存,而是要过段时间再减小。现象是某个时刻窗口变为0,但是窗口增大的报文丢失了,双方互相等待。解决方法是启用一个定时器,如果在一个定时器内没有收到报文,就会发送窗口探测报文。(一般发送三次,如果还没收到任何消息就发送RST报文)
- 糊涂窗口:现象是接收方处理数据的速度过慢,导致窗口只能越来越小,而发送方有多少发多少(TCP包头占比越来越大),就会逐渐导致窗口塞满。解决方法是接收方当窗口小于 min(MSS, 缓存空间/2) 时直接通知窗口大小为0,直到窗口恢复。发送方如果当可用窗口大小 >= MSS 且 可发送的数据 >= MSS才发送数据,否则如果有发送过但未确认的数据就等待,如果没有就发送数据。
拥塞控制
- 定义:流量控制参考的是的时接收方,而拥塞控制参考的是网络状况。如果不进行拥塞控制,会导致网络中出现大量时延、丢包,然后进行重传,导致恶性循环。实时维护发送窗口 swnd = min(拥塞窗口 cwnd , 接收窗口 rwnd)。
- 机制:
- 慢启动:TCP 在刚建立连接完成后,需要慢启动。原因是不明网络情况直接发送大量数据后果未知。初始cwnd为一个设定的值,之后每接收到一个ACK报文,窗口大小加一个MSS。这个过程 cwnd 是指数级增长的: cwnd 越大发送的包越多,包越多ACK越多,增长的越快。增长的上限是慢启动门限(ssthresh),到达ssthresh之后,进入拥塞避免。
- 拥塞避免:每接收到一个ACK报文,窗口大小加 1/cwnd 个MSS。这个过程 cwnd 是线性增长的。
- 拥塞发生:拥塞判断条件是发生数据包重传。超时重传时,ssthresh = cwnd/2,cwnd恢复初始值,重新进入慢启动。快速重传时,ssthresh = cwnd/2,快速恢复算法因收到了三个同样的ACK触发重传故cwnd = ssthresh + 3MSS。如果再收到重复的 ACK,那么 cwnd 增加 1MSS。直到收到了新的ACK,把 cwnd 设置为 ssthresh ,恢复过程结束。