遇到的 超时重传

之前有一篇文章说到了RTT RTT__RTO

TCP使用一个重传定时器来在缺少数据接收端反馈的情况下保证数据到达,这个定时器时间被称为RTO(retrnasmission timeout)

 从这个报文中可以看到:服务端的报文没有被确认导致发生超时重传

那要怎么处理这个问题呢?

RTO基本算法:https://tools.ietf.org/html/rfc6298   见rfc

协议中主要有两种方法来计算RTO一种是RFC793的经典方法(classic method),另一种是RFC6298的标准方法(standard method)。

1、RTO计算及更新

为了计算当前的RTO,TCP发送端维护两个状态变量一个是SRTT(smoothed round-trip time)一个是RTTVAR (round-trip   time variation),另外还有一个TCP时钟粒度G。

  • 1)、在没有测量到有效的RTT采样之前,设置RTO=1s;

  • 2)、在第一个有效的RTT采样测量出来后,假设采样值为R,则进行如下初始化过程

srtt为经过平滑后的RTT值,它代表着当前的RTT值,每收到一个ACK更新一次。为了避免浮点运算,它是实际RTT值的8倍。

rttvar可升可降,代表着连接的抖动情况,在连接断开前都有效。

SRTT = R

RTTVAR = R/2

RTO = SRTT + max(G,K*RTTVAR)

其中K = 4;

  • 3)、当随后的RTT采样R’测量到以后,按照如下更新:

RTTVAR = (1 - beta) * RTTVAR + beta * |SRTT - R'|            

SRTT = (1 - alpha) * SRTT + alpha * R'

注意用于计算RTTVAR的公式中的SRTT是本次更新前的值,也就是说这两个公式的计算顺序不能颠倒。其中alpha=1/8、 beta=1/4,alpha和beta的选值允许计算机通过移位做除法的快速运算。

计算出SRTT和RTTVAR后,RTO仍旧按照如下更新:

RTO = SRTT + max (G, K*RTTVAR)

  • 4)、当RTO计算出来后,如果RTO小于1s,RTO则应该设置为1s。虽然给出的是1s的下限,但是协议允许使用更低的下限。

  • 5)、也可以对RTO设置一个上限,协议建议上限至少为60s。

关于上面的RTT采样,协议要求使用karn算法进行采样,同时要求至少在一个RTT里面采样一次(除非因为karn算法导致不可能在一个RTT里面采样一次)。协议指出对于每个TCP报文进行RTT采样测量不一定会得到更好的RTT估计值。

# 计算平滑 RTT
SRTT = SRTT + α (RTT – SRTT)
 
# 计算平滑 RTT 和 真实 RTT 的差距
DevRTT = (1-β)*DevRTT + β*(|RTT-SRTT|)
RTO = µ * SRTT + ∂ * DevRTT
Linux 下,α = 0.125,β = 0.25,μ = 1,∂ = 4, 其中 DevRTT 表示 Deviation RTT (标准差 RTT )。

参考:https://www.cnblogs.com/lshs/p/6038535.html

具体对错 就那样吧。。。。

RTO定时器管理

  • 1)、每次一个包含数据的TCP报文发送出去的时候(包括重传),如果RTO定时器没有运行,则重启RTO定时器,并设置定时时间为RTO。

  • 2)、当所有发出的数据报文都被ACK后,关闭这个RTO定时器。

  • 3)、当一个新的ack number到达的时候(新的ack number是指ack了新数据),如果还有未被ACK的数据,则重启RTO定时器,并设置定时时间为当前RTO。

当RTO定时器触发的时候(即所设置的定时时间到达的时候)

  • 4)、在还没有ACK的报文里面重传最早发出去的报文。

  • 5)、设置RTO = RTO * 2,这也就是我们经常说的指数回退。也可以和上面RTO更新过程一样添加一个同样的上限来限制RTO大小。

  • 6)、重启RTO定时器,设置定时时间为RTO(这里的RTO是已经回退过的RTO)。

  • 7)、如果RTO定时器是因为等待SYN报文的ACK而超时,如果实现上使用的RTO值小于3s,这个RTO定时器必须被重新初始化为3s。

    在重传完成后,新的RTT采样可能会将RTO设置为与原来比较接近的值,从而消除指数回退对于RTO的影响。另外在多次指数回退过程中,TCP实现可能会清空SRTT和RTTVAR的值,一旦这两个被清空,则需要使用上面RTO计算及更新中的第2)步来初始化SRTT和RTTVAR。

/* 最大RTO为120s,退避时不能超过这个值 */
#define TCP_RTO_MAX    ((unsigned)(120*HZ))
/* 最小RTO为200ms,rttvar不能低于这个值 */ 
#define TCP_RTO_MIN    ((unsigned)(HZ/5))
/* 初始RTO为1s */
#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ))    /* RFC6298 2.1 initial RTO value    */
#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ))    /* RFC 1122 initial RTO value, now
                         * used as a fallback RTO for the
                         * initial data transmission if no
                         * valid RTT sample has been acquired,
                         * most likely due to retrans in 3WHS.
                         */

回到正题:现在已经丢包了, 怎么解决能让他不丢包, 客户端那边是仪器, 也只能调整服务端了!!

修改RTO 貌似不可能

那只能 修改重传次数&& 超时重传最大时间??

 net.ipv4.tcp_retries1:TCP 在向 IP 层传递前,愿意尝试重传的次数,也就尝试别的路由出去?

 net.ipv4.tcp_retries2: TCP 放弃当前连接时,尝试重传的次数

对于 SYN 报文段,变量 net.ipv4.tcp_syn_retries  和 net.ipv4.tcp_synack_retries 限定重传次数

原文地址:https://www.cnblogs.com/codestack/p/14247898.html