目录
- TCP超时重传
- 拥塞控制
- 概述
- 慢启动和拥塞避免
- 下面讲解发送端如何判断拥塞发生。
- 快速重传和快速恢复
本文描述TCP在异常网络下的处理方式 以保证其可靠的数据传输的服务
TCP超时重传
tcp服务能够重传其超时时间内没有收到确认的TCP报文段,tcp模块为每一个报文段都维护一个重传定时器,定时器在第一次TCP报文段发送的时候启动,如果超时事件内没有收到回复。Tcp模块就会重传该报文段并重置定时器
至于下次重传的事件 和最多的重传次数 就是重传策略的选择。
liunx内核有两个重要的内核参数和tcp超时重传相关:
/proc/sys/net/ipv4/tcp_retries1
/proc/sys/net/ipv4/tcp_retries2
前者指定了底层IP接管TCP最少执行的重传次数 ,默认3
后者指定连接放弃前TCP最多可以执行的重传次数 默认15(一般对应13 - 30min)
虽然超时会导致TCP报文段重传,但是tcp报文段的重传可以发生在超时之前,即快速重传。
拥塞控制
概述
拥塞控制的目的是
- 提高网络利用率
- 降低丢包率
- 保证网络资源对每条数据流的公平性
拥塞控制标准文档是RFC 5861 四个部分:
- 慢启动(slow start)
- 拥塞避免(congestion avoidance)
- 快速重传(fast retransmit)
- 快速恢复(fast recovery)
拥塞控制算法在liunx上 有多种实现,比如reno算法,vegas算法和cubic算法等。它们或者部分或者全部实现了上面上述四个部分.
/proc/sys/net/ipv4/tcp_congestion_control 文件指示机械当前所使用的拥塞控制算法
在发送端一次向网络中连续写入的数据量(收到其中第一个数据的确认之前) 我们称为SWND(Send Window 发送窗口) 发送端最终以TCO的报文段来发送内容 所以SWND限定了发送端能发送的TCP报文段的数量。
TCP报文段的最大长度(数据部分) 被称为SMSS(Sender MAximum Segment Size ,发送者最大段的大小) 其值一般等于MSS
MSS的值通常是由MTU(Maximum Transmission Unit,最大传输单元)减去IP首部长度(20字节)和TCP首部长度(20字节)得到的。因此,如果MTU值为1500字节,那么MSS的值一般就是1460字节)。
发送端需要合理的选择SWND的大小 ,如果SWND太小会引起明显的网络延迟 反之如果太大则会导致网络拥塞。
接收方虽然可以通过RWND来控制发送端的SWND,但是显然不够
发送端引入了一个称为拥塞窗口的状态变量(CWND) 实际的SWND值 是RWND和CWND里面的较小者
下图显示了拥塞控制的输入和输出
慢启动和拥塞避免
Tcp创建好连接后 CWND的值被初始化为IW(initial Window ) 其大小为2~4个SMSS。但新的Liunx内核提高了该值的初始化,以减少传输滞后。
发送端最多可以发送IW字节的数据 ,此后发送端没收到一个及手段的确认。其CWND就按格式增加
cwnd +=min(N,SMSS)
(读者在其他地方也可以看到了 cwnd是直接加上一个SMSS的值的 这个我不太清 查资料没查到 欢迎指正)
其中的N表示 此次确认中包含之前未被确认的字节数。
这样CWND将会按指数的形式扩大,这就慢启动。
慢启动算法的理由是,TCP模块刚开始发送数据并不知道网络的实际情况,需要一种探测的方式平滑的增加CWND的小事。
如果不是家其他手段 慢启动必然会使得 CWND很快膨胀最终导致网络拥塞。因此TCP拥塞控制汇总顶一个另一个重要的状态变量:
慢启动门限(ssthresh) 当CWND的大小超过该值的时。TCP拥塞控制将进入拥塞避免阶段。
拥塞避免算法是的CWND按照线性的方式增加 从而减缓起扩大.RFC 5681中提到了如下两种实现方式:
- 每个RTT时间内按照格式从新计算新的CWND,不论RTT事件内收到了多少个确认
- 没收到一个新的数据确认报文段,就按照下面公式来更新CWND
- CWND +=SMSS*SMSS/CWND
下图粗略描述了慢启动和拥塞避免发生的时机和区别。 假设ssthresh的大小是16SMSS大小 实际远不止这么大
以上是发送端在未检测到拥塞时所采取的积极避免拥塞的方法。
下面介绍拥塞发生时(可能在慢启动 也可能在拥塞避免阶段) 拥塞控制的行为。
下面讲解发送端如何判断拥塞发生。
- 传输超时,或者TCP重传定时器溢出
- 接受到重复的确认报文段
拥塞控制对第一种情况仍然使用慢启动和拥塞避免。
第二种情况使用快速重传和快速恢复(如果真的发生拥塞的话)。
第二种情况如果发生在第一种情况之后也就是重传定时器溢出,也会被拥塞控制当成第一种情况来对待。
如果发送端检测到拥塞发生是由于传输超时 它就会执行重传并做出一下调整
其中FlightSize是已经发送但是没有收到确认的字节数。这样调整 CWMD将小于SMSS。必然也小于新的慢启动门限值ssthresh
拥塞控制一定会再次进入慢启动阶段
快速重传和快速恢复
有时发送端可能接收到重复的确认报文段,如TCP报文段丢失 或者接收端收到乱序的TCP报文段并重排的时候,拥塞控制算法需要判断当收到重复确认的报文。网络是否真的拥塞 或者TCP报文段是否真的丢失。
具体的做法是当发送端连续收到三个重复的确认报文段 就认为是拥塞发生。就会启动快速重传和快速恢复算法来吃处理拥塞
过程如下:
- 当收到三个重复的确认报文的时候 按照
来计算ssthresh,然后立刻重传丢失的报文段
并按照
来设置CWND - 每次收到一个重复的确认的时候 ,设置CWND=CWND+SMSS。 此时发送端可以发送新的TCP报文段。如果新的CWND允许的话
- 当收到新的数据确认的时候 设置CWND = ssthresh(ssthresh是新的慢启动的门限值)由第一步计算得到
快速重传和快速恢复完成之后 拥塞控制将恢复的拥塞避免阶段 这一点由第3 步可以知道