这里只是简单梳理TCP各版本的控制原理,对于基本的变量定义,可以参考以下链接:

TCP基本拥塞控制http://blog.csdn.net/sicofield/article/details/9708383

TCP中RTO计算http://www.tuicool.com/articles/Yn6vEr

TCP拥塞控制名词解释:

1.awnd(advised window) 通告窗口,由接收端tcp发送给发送端tcp,告诉发送端自己能用于接收新的数据包的当前可用空间。

2.cwnd(congestion window)拥塞窗口,人为引入的变量,用于拥塞控制。因为如果单独使用awnd,每次都按接收端最大窗口发送易引发网络的瞬时拥塞瞬时进入拥塞避免剧烈降低网络利用率。

3.ssthresh(slow start thresh)慢启动阈值,用于确定使用慢启动算法还是拥塞避免算法。当前窗口小于ssthresh的时候,使用慢启动算法按指数增加窗口;当前窗口等于ssthresh时,使用慢启动或拥塞避免算法增长发送窗口都可以;当前发送窗口大于ssthresh时,使用拥塞避免算法,按线性增加发送窗口。

4.发送窗口W = min(cwnd, awnd)

5.duplicate ACK重复ACK,TCP接收端在接受到错序/失序数据包时应该立即向发送端返回重复ACK。如接收端已经顺序收到1000号前的包,返回发送端1001,然后接收端接着收到了1002号包,而不是期望的1001号包,则其立即返回给发送端1001的ACK包,这个ACK相对于第一次的1001ACK就是重复ACK包。

原始版TCP协议--TCP-Tahoe:

1.慢启动

初始值cwnd=1(linux3.0之后是10),ssthresh初始值可以被设置为任意大(可以设置为awnd或更大,这样总是使TCP从慢启动算法开始,而不是拥塞避免算法),如linux 3.2.12是int最大值0x7fffffff.

该阶段,每个rtt周期发送窗口W加倍。时间曲线图中表现为指数曲线。

2.拥塞避免

如果出现丢包,由于TCP无法确认丢包类型,所以就认为发生了网络拥塞,重传包并进入拥塞避免算法。操作是:

ssthresh = max(flight size/2, 2*SMSS),flight size为当前发送窗口中已经发送但还没有收到ACK的包个数,即flight size<=W,SMSS为发送端最大分组大小。

cwnd=1(或其他初始值,如10),然后就可以重新从慢启动算法增加发送窗口。

3.丢包,重现慢启动

在上一步的基础上,根据新的初值,回到第1步重新执行慢启动。

如下图:

说明:

1.tcp启动时,cwnd=1,ssthresh=16,时间轴0-4是慢启动算法阶段。然后发送窗口增加到ssthresh时,进入拥塞避免阶段,时间轴4-12.

2.发送丢包时,cwnd重新置为1,ssthresh设置为当前拥塞窗口(24)的一半,即12.时间轴上12-13.

3.上一步设置完新的cwnd和ssthresh后,重新进入第1步进行执行慢启动算法。

后期Tahoe版本也引入了快重传算法(原始检测到丢包需要等到rto超时才能重传,快重传就是连续收到3个ack就立即重传)。

快恢复版本TCP--TCP-Reno(增加快重传/快恢复算法):

Tahoe版本检测丢包只能通过RTO超时依然收不到ACK时才能开始重传,Reno版的修改是,引入快重传机制:当收到对方连续3次重复ACK时,不必再等待RTO超时,认为网络已经发生拥塞丢包,立即重传数据包。同时,因为RTO时间内连续收到3次ACK,认定网络状况依然良好,丢包可能是网络发生了瞬时拥塞。所以不必对发送窗口进行过度调整。

快重传机制(Fast Retransmit):

当收到3次连续的重复ACK时,立即重传数据包,不必等待RTO超时。

注意:快重传不必一定跟快恢复算法同时使用。Tahhoe版本中也可以使用快重传,但cwnd依然调整为1,而不是快恢复算法的cwnd/2.

窗口示例:

快重传/快恢复算法(Fast Recovery):

1.收到3次重复ACK,设置ssthresh=cwnd/2。

2.重传丢失的包,设置cwnd=ssthresh+3。3是根据网络“数据包守恒”定律,即根据ACK机制,收到3个重复ACK,说明有3个数据包已经离开了网络,所以cwnd+3。

3.每收到一个额外的重复ACK(包5),cwnd=cwnd+1。只是为了反应出一个包已经离开网络的事实。

4.传输包

5.如果收到新数据包的ACK(包7或包9),cwnd=ssthresh,称为“缩小窗口”,退出快恢复阶段,进入拥塞避免阶段。

对应下图时间轴12-13.

总结:

TCP拥塞控制算法 RFC文档链接http://www.faqs.org/rfcs/rfc2581.html

新版本TCP--TCP NewReno(相对Reno少量但却重要的修改是对partial acknowledgment部分确认的处理):

Reno版本不足:

当发送窗口只有一个包丢失,则快重传后,一个rtt后收到的第一个ack会确认快重传启动之前全部已经发送的数据包。但是如果发送窗口中多个包丢失,那么快重传后第一个收到的ack只能确认发送窗口中的部分数据,称为“部分确认”。NewReno处理“部分确认”的方法是,认为那个包丢失并重传那个包。

NewReno新的快重传/快恢复算法:

1.当收到3次重复ACK,并且发送者并不处于快恢复过程时

设置ssthresh = cwnd/2

记录recover=max sequence number,快重传算法之前已传输的最大的数据包序列号(包10或更大)。

2.重传丢失包(包5),设置cwnd=ssthresh+3

3.如果继续收到重复ACK(包5),cwnd=cwnd+1

4.发送包(由于上一步cwnd窗口扩张)

5.当收到新的数据包的ACK(包7或包9),这个ACK可能是对第2步重传或稍后的重传的确认。

if (ACK确认所有的从丢失包一直到并包括“recover”的数据包)

  设置cwnd=ssthresh或min (ssthresh, FlightSize + MSS),然后退出快恢复阶段。

else

  重传下一个没有被确认的数据包;将cwnd=cwnd-新确认的数据包个数+1,发送新的包。这样缩小窗口的目的是,当快恢复算法最终退出时,大约有ssthresh数量的数据包存在于网络中。如果收到新的ack,重复执行第3-4步。

总结:

TCP NewReno RFC文档链接http://www.faqs.org/rfcs/rfc2582.html

有理解错误的地方,欢迎指出。

Linux TCP拥塞控制算法原理解析的更多相关文章

  1. TCP拥塞控制算法纵横谈-Illinois和YeAH

    周五晚上.终于下了雨.所以也终于能够乱七八糟多写点松散的东西了... 方法论问题. 这个题目太大以至于内容和题目的关联看起来有失偏颇.只是也无所谓,既然被人以为"没有方法论"而歧视 ...

  2. TCP拥塞控制算法

    转自浅谈TCP拥塞控制算法 本篇文章介绍了几种经典的TCP拥塞控制算法,包括算法原理及各自适用场景. 回顾上篇文章:浅谈 redis 延迟 前言 TCP 通过维护一个拥塞窗口来进行拥塞控制,拥塞控制的 ...

  3. TCP拥塞控制算法 优缺点 适用环境 性能分析

    [摘要]对多种TCP拥塞控制算法进行简要说明,指出它们的优缺点.以及它们的适用环境. [关键字]TCP拥塞控制算法 优点    缺点   适用环境公平性 公平性 公平性是在发生拥塞时各源端(或同一源端 ...

  4. 让人非常easy误解的TCP拥塞控制算法

    正文 非常多人会觉得一个好的TCP拥塞控制算法会让连接加速,这样的观点是错误的.恰恰相反,全部的拥塞控制算法都是为了TCP能够在贪婪的时候悬崖勒马,大多数时候.拥塞控制是减少了数据发送的速度. 我在本 ...

  5. 浅谈TCP拥塞控制算法

    TCP通过维护一个拥塞窗口来进行拥塞控制,拥塞控制的原则是,只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入 ...

  6. 【转载】TCP拥塞控制算法 优缺点 适用环境 性能分析

    [摘要]对多种TCP拥塞控制算法进行简要说明,指出它们的优缺点.以及它们的适用环境. [关键字]TCP拥塞控制算法 优点    缺点   适用环境公平性 公平性 公平性是在发生拥塞时各源端(或同一源端 ...

  7. 网络拥塞控制(三) TCP拥塞控制算法

    为了防止网络的拥塞现象,TCP提出了一系列的拥塞控制机制.最初由V. Jacobson在1988年的论文中提出的TCP的拥塞控制由“慢启动(Slow start)”和“拥塞避免(Congestion  ...

  8. TCP拥塞控制算法之NewReno和SACK

    TCP拥塞控制算法之NewReno和SACK 2018年05月23日 19:10:03 吃吃爱学习 阅读数:1446    版权声明:程序媛吃吃的博客 https://blog.csdn.net/m0 ...

  9. TCP拥塞控制算法内核实现剖析(十)

    内核版本:3.2.12 主要源文件:linux-3.2.12/ net/ ipv4/ tcp_veno.c 主要内容:Veno的原理和实现 Author:zhangskd @ csdn blog 概要 ...

随机推荐

  1. 揭密FutureTask

    Future是我们在使用java实现异步时最常用到的一个类,我们可以向线程池提交一个Callable,并通过future对象获取执行结果.本篇文章主要讲述了JUC中FutureTask中的一些实现原理 ...

  2. 在vs2010中编译log4cxx-0.10.0详细方法(从下载、编译、解决错误详细介绍)

    在vs2010中编译log4cxx-0.10.0详细方法(从下载.编译.解决错误详细介绍) http://blog.sina.com.cn/s/blog_a459dcf501013tbn.html

  3. Java-Runoob-高级教程-实例-字符串:05. Java 实例 - 字符串反转

    ylbtech-Java-Runoob-高级教程-实例-字符串:05. Java 实例 - 字符串反转 1.返回顶部 1. Java 实例 - 字符串反转  Java 实例 以下实例演示了如何使用 J ...

  4. [html]window.open 使用示例

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. Maven的依赖机制介绍

    以下内容引用自https://ayayui.gitbooks.io/tutorialspoint-maven/content/book/maven_manage_dependencies.html: ...

  6. 简单神经网络TensorFlow实现

    学习TensorFlow笔记 import tensorflow as tf #定义变量 #Variable 定义张量及shape w1= tf.Variable(tf.random_normal([ ...

  7. Web Api HelpPage

    为了方面APP开发人员,服务端的接口都应当提供详尽的API说明.但每次有修改,既要维护代码,又要维护文档,一旦开发进度紧张,很容易导致代码与文档不一致. Web API有一个Help Page插件,可 ...

  8. [Delphi] FMXUI - 沉侵式状态栏

    好消息!FMXUI正式支持Android和IOS的沉侵式状态栏了. 先来看看效果图 安卓: IOS: 一.Android 沉侵式状态栏 FMXUI的沉侵式状态栏支持SDK版本大于21的Android系 ...

  9. cpu真实核数

    判断依据: 1.具有相同core id的cpu是同一个core的超线程. 2.具有相同physical id的cpu是同一颗cpu封装的线程或者cores. 英文版: 1.Physical id an ...

  10. 读书笔记--Linux Shell脚本攻略

    总结的来说,这本书很实践性和实用性强,都是给的具体的例子,直接可以在终端操作实践,比单纯只看不动手务实多了,另外就是,这本书涵盖的内容也比较广,从文本操作到服务器管理到远程ssh等等,都给出来作者挑选 ...