TCP的确认和重传机制
- 基本确认机制
接收方每收到一个TCP分段都会回应一个ACK号,ACK号等于下一次发送报文的序列号。
累积确认是TCP的强制特性,所有TCP实现都要实现这一特性。ACK确认号是累积的,表示该序号之前的所有数据均已正确接收。若中间有丢失,接收方会重复发送之前的ACK(如Ack=101),触发发送方重传。
- 延迟确认
开启后当收到全大小的分段(即MSS大小)时会等待下一个分段到来时一起发送ACK号,RFC 1122要求收到全大小分段时每两个分段发送一个ACK。如果第2个数据包一直没有到达会在延迟确认时间超时后发送ACK号。延迟确认的超时时间不能大于超时重传的超时间。在Linux上这个值在40ms到200ms之间。
- 超时重传
如果超过了指定时间还没有收到ACK,则认为数据丢失,并从最后收到ACK号开始重传所有后续的包。重传超时时间称为RTO,在Linux上这个值在200ms到120s之间。
重传超时时间RTO是跟据RTT计算的,RTT是根据ACK到达时间算的,RTO一般是RTT的1到4倍,但始终在200ms至120s这个范围内。
- 快速重传
接收端如果收到乱序包就会认为发生了丢包,这时候每收到1个新的包就会发送一个相同的ACK(乱序前最后的ACK),这样发送端如果收到3个相同的ACK就会立即发送ACK指定序列号的分段。
快速重传优点是一次只需要重传一个包,但是缺点也是只能重传一个包(如果丢包多的话)。
在Reno算法中会利用快速重传机制进行快速恢复。
- SACK
SACK是一个扩展选项,SACK选项附带了丢失报文的超始序列号和结束序序号,一个SACK选项可以携带多组不连续的丢失报文边界。因为TCP可选选项的长度最大是40字节,所以一个TCP分段可以携带4个SACK区段的边界。
- DSACK
DSACK的选项格式也SACK一样,但DSACK描述的是收到的重复报文的区间,这样让发送者知道哪些报文发重了,从而调整发送策略。
- PSH标志
默认情况下TCP发送数据时尽可能使用大包而不是小包,连续的小包会一起在缓冲区中暂存,合并为一个大包一起发送出去。当使用PSH标志时带有PSH标志的分段分立即发送出去(包含当前分段前面未发送的数据)。接收方收到带有PSH的分段也会立即提交给应用层。
PSH标志不会改变数据分段的发送顺序,URG标志则会改变数据分段的发送顺序。
在Linux系统中当缓冲区没有后续数据时也会立即把数据发送出去并设置PSH标志。
一般情况下发送数据量大时(开启Nagle算法且缓冲区满)就会执行包合并,如果数据量很小也会立即发送出去而没有包合并的机会,如果关闭Nagle算法则任何情况都不会执行包合并(网卡中靠硬件执行的LRO Offload除外)。
设置PSH标志可以避免网卡执行LRO Offload(网卡有Bug除外)。
关于数据的合并和发送规则可以参考Nagle算法。
Views: 0