TCP 超时管理 "TCP/IP详解" 第十四章 读书笔记

2020-10-06  本文已影响0人  再凌

连接建立时发生失败或传输数据超时

连接发起方会以指数级等待, 并尝试重新建立连接

R1: TCP认为超时过多, 应该报告IP层(重新路由)
R2 : TCP判定连接建立失败(报告应用层)

R1R2可以在系统层面修改, 数值代表发送失败的次数而不是具体秒数, 秒数根据RTO测定

超时重传

RTO = rtt_mean + 4 * rtt_var

在Linux实现中将测量周期从50ms变到了1ms, 虽然测量更加准确, 但是有以下几个问题

RTO测量基于Timestamp特性(如果没有Timestamp则普遍只维护一个测量样本, 使用后可同时测量多个样本), 返回的ack包包括了SYN发送过来的时间, 那么发送端根据自己的时钟就能测量出链路RTT

RTT测量会忽略0大小的包, 如KeepAlive包等, 同时这些包的特征是"不提供可靠交付"

这种Linux的测量方法相比于传统方法更加鲁棒:


超时重传是tcp的"兜底策略", 因为RTO一般是2*RTT, 多数情况都是使用快速重传完成了重传的过程.

快速重传

当失序报文到达的时候, 立刻返回ACK. 如果采用了SACK, 那么也会携带SACK信息来得知多个空缺.

对于发送端, 收到多个ack可能是丢失了, 也可能只是延迟到达, 所以发送端需要累积多个ack才决定重发.

如果不采用SACK, 至多只能重传一个片段. 直到收到了出现重传状态前应该收到的ACK包时才认为恢复了(newReno算法), 只要收到了任何一个可接受的ACK则认为恢复了(老Reno算法)

每个SACK信息需要32位来描述ACK位置, 即每个区间需要2*4个字节来描述, tcp扩展有40个字节, 使用TimeStamp用掉10字节, 2个字节标志位, 因此最多能够标识3个SACK区间

但是在SACK中, 发送端也只能重传一个片段, 直到得知这个区间已经被确认.

SACK核心思想: 在一个RTT内填补更多的空缺区间

伪重传现象

由于ACK报文传输时间过长导致的发送端认定应当重传的现象

会导致发生了回退N, 浪费带宽.

Eifel检测算法或者DSACK. DSACK复用了SACK的字段来告知发送端有的报文重复了. Eifel算法使用了TimeStamp, 发送端发送了重传后, 如果收到的TimeStamp是对于前一个报文的确认, 则认为是伪重传.

Eifel算法能够更早发现伪重传, 因为DSACK需要在接收端也感知到伪重传并构造DSACK

F-RTO算法: 能够避免超时重传引起的伪重传: 发生超时重传时, 仍然坚持发送之后的报文, 如果能收到这个报文的ACK, 证明接收方窗口移动了, 说明不需要重传.

还有一种是"重复"现象: 在传输过程中由于数据链路层退避算法导致数据包被复制传输, 接收方收到了多个重传但是发送方并不之情. 接收方会回复多个确认, 可能会引起重传. 如果使用了DSACK可以有效避免.(接收方的回复中报告了自己已经成功接收)

重新组包

TCP通过字节号来识别数据而不是报文段或者包

因此在SACK重传的时候允许同时在这个包携带下一个要发送的数据, 组成一个更大的数据包, 甚至这两篇数据顺序都不重要.

攻击

预测重传时间, 在要重传的时候发动DDOS攻击, 让对方发不出去

伪造ACK, 提前确认, 让发送方一位RTO很小, 从而浪费带宽提前发送很多无效数据

上一篇下一篇

猜你喜欢

热点阅读