上一篇http://www.cnblogs.com/whc-uestc/p/4715334.html中已经讲到TCP跟踪一个拥塞窗口来(cwnd)提供拥塞控制服务,通过调节cwnd值以控制发送速率。那么TCP如何基于丢包事件来设置cwnd值?通过TCP拥塞控制算法来实现。TCP拥塞控制算法主要有三部分:慢启动、拥塞避免、快速恢复。

1、慢启动

  当一条TCP连接开始时,cwnd的值一般初始设置为MSS的较小值。因为只有当发送方接收到ACK,才会更新cwnd的值,所以在一个RTT时间内,发送方只能发送cwnd字节大小的数据,这就使得初始发送速率大约为MSS/RTT。这是一个较小的值,大部分的带宽还是空闲的,如何迅速更新cwnd以提高带宽利用率??

  慢启动状态:cwnd的值以1个MSS开始并且每当传输的报文段首次被确认就增加一个MSS。

  • 刚开始在第一个RTT中,cwnd只有1个MSS,发送一个报文;
  • 收到一个ACK,此时cwnd增加1个MSS,在第2个RTT,cwnd为2个MSS,发送两个报文;
  • 会收到两个ACK,此时cwnd增加2个MSS,所以在第3个RTT中,cwnd为4个MSS,发送4个报文;
  • 依次类推。

  从上面的过程,不难发现每过一个RTT,发送速率就会翻一倍。虽然起始速率只有MSS/RTT,但是在慢启动的过程中是以指数增长的。当然,带宽是有限的,发送速率不可能无限制地增长,那么问题来了,什么时候结束这种指数增长??

  (1) 当有一个超时引起的丢包事件(拥塞)时,TCP发送方将cwnd设置为1并重新开始慢启动过程;同时将慢启动阈值ssthresh设置为cwnd/2。

  (2) 在(1)重新慢启动过程中,当cwnd的值增长到大于等于慢启动阈值ssthresh时,慢启动结束,同时转移到拥塞避免模式

   (3) 如果在慢启动的过程中,发送方收到3个冗余的ACK,TCP就结束慢启动过程,执行快速重传并进入快速恢复模式

2、拥塞避免

  上面说到,只有当再次启动慢启动并且cwnd增长到大于等于慢启动阈值ssthresh时,才会进入拥塞避免模式,所以当进入到拥塞避免时,cwnd的值大概是在第一次遇到拥塞时的cwnd的值的一半。此时如果继续进行慢启动就会使cwnd的值翻倍从而可能导致拥塞。所以拥塞避免模式对于每次收到的ACK,并不像慢启动那样直接将cwnd增加一个MSS字节,而是增加MSS*MSS/cwnd字节。也就是说当MSS=1460字节,cwnd为14600字节,那么每次收到一个ACK,cwnd增加1460*1/10字节,只有收到10个ACK,cwnd才会增加一个MSS。

  问题来了,与慢启动一样,难道cwnd的值也是这么一直增长下去么??什么时候结束呢?

  (1) 当有一个超时引起的丢包事件(拥塞)时,同慢启动一样,TCP发送方将cwnd设置为1并重新开始慢启动过程;同时将ssthresh设置为cwnd/2。

   (2) 当收到3个冗余的ACK时,ssthresh设置为cwnd/2,TCP将cwnd的值设置为ssthresh+3进入快速恢复模式

3、快速恢复

  对于引起TCP进入快速恢复状态的缺失报文段,对收到的每个冗余ACK,cwnd的值增加1个MSS,当收到新的ACK时TCP把cwnd设置为ssthresh的值进入拥塞避免状态

  当在快速恢复阶段出现超时事件,cwnd的值被设置为1个MSS,并且ssthresh的值设置为cwnd的一半,进入慢启动状态

  TCP的拥塞控制其实是加性增、乘性减(AIMD)的拥塞控制方式,当TCP连接的路径上没有拥塞(通过判断丢包事件)时,发送速率加性增;当出现丢包事件时,发送速率乘性递减。我们知道UDP本身是没有实现拥塞控制的,其实如果大量使用UDP而没有任何约束,那么网络就很容易出现死锁,使得端到端之间很少有数据能够被传输。

4、总结:

  当然,虽然UDP是不可靠、无连接的传输层协议,而TCP是面向连接的提供可靠数据传输的传输层协议。但是UDP的应用依旧很广,像DNS,QQ都是用的是UDP,很多人会奇怪,为什么TCP提供了那么多服务,为什么不用TCP而用这么不可靠的UDP呢??

  其实无论TCP还是UDP,在如此复杂的网络中,并不可能是完全可靠的。

  • TCP只是通过确认和重传机制来保证它的可靠性,而UDP并没有确认和重传机制。
  • TCP提供有序的数据流服务,UDP每个数据包是单独的,在接收方并不保证提交给应用层的数据包是有序的。
  • TCP提供流量控制和拥塞控制,通过流量控制,可以让发送方和接收方的应用层从接收缓冲区读取数据的速率匹配,从而不会因为接收缓冲区满而发生丢包;通过拥塞控制,每一个通过拥塞链路的TCP连接都能够平等地共享链路带宽。

  但是正因为TCP提供了这么多的服务,使得TCP变得很臃肿,很难发送大容量的数据;这时候,轻量的传输层协议UDP就站出来了。UDP很简单,不提供那么多的机制和服务,使得UDP的传输速率可以比TCP快很多。当然有人会说,UDP丢包率很高,UDP接收到无序的数据包,UDP没有拥塞,可能导致网络瘫痪等等一些问题。

  因为传输层及以上的层次都是只在端系统中实现的,在网络分组交换机中只有网络层一下的实现,也就是说TCP的所有这些服务都是基于端到端的服务。既然是端到端的服务,那么上述的所有问题都可以通过上层(也就是应用层)来实现,通过在应用层把发送的数据进行编号,就可以在接收端对接收的数据进行排序,从而的到有序的数据;通过在应用层添加确认和重传,就可以大大降低丢包率;通过在应用层加一个窗口,来达到流量控制和拥塞控制的目的。当然具体基于UDP的实现其实并不需要把所以TCP的服务都在应用层实现,否则还不如用TCP。我们只需要实现那些我们需要和关系的服务即可,比如说我们需要降低丢包率,我们就只实现重传机制。(当然我们也可以完全不用传输层,应用层直接通过网络层通信)

  UDP很自由,可以任由上层来实现;TCP很全面,可以给上层提高可靠的数据传输和各种机制。到底选择哪一种传输层协议,其实还要根据具体的应用来选择。存在既有价值,关键是各方面的权衡而已。

版权所有,欢迎转载,转载请注明出处。

深入理解TCP(二)的更多相关文章

  1. ppp 完全理解(二)【转】

    转自:https://blog.csdn.net/tianruxishui/article/details/44057717 ppp 完全理解(二) pppd 协议及代码分析 作者:李圳均 日期:20 ...

  2. 结合Wireshark捕获分组深入理解TCP/IP协议栈

    摘要:     本文剖析了浏览器输入URL到整个页面显示的整个过程,以百度首页为例,结合Wireshark俘获分组进行详细分析整个过程,从而更好地了解TCP/IP协议栈.   一.俘获分组 1.1 准 ...

  3. 简单理解TCP/IP协议

    一.什么是TCP/IP TCP/IP是一个协议族,是因为TCP/IP协议包括TCP.IP.UDP.ICMP.RIP.TELNETFTP.SMTP.ARP.TFTP等许多协议,这些协议一起称为TCP/I ...

  4. 深入理解TCP建立和关闭连接

    建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...

  5. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  6. C++ 中类的构造函数理解(二)

    C++ 中类的构造函数理解(二) 写在前面 上次的笔记中简要的探索了一下C++中类的构造函数的一些特性,这篇笔记将做进一步的探索.主要是复制构造函数的使用. 复制构造函数 复制构造函数也称拷贝构造函数 ...

  7. Java 反射理解(二)-- 动态加载类

    Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编 ...

  8. 如何理解TCP的三次握手协议?

    • TCP是一个面向链接的协议,任何一个面向连接的协议,我们都可以将其类比为我们最熟悉的打电话模型. 如何类比呢?我们可以从建立和销毁两个阶段分别来看这件事情. 建立连接阶段 首先,我们来看看TCP中 ...

  9. 【PHPsocket编程专题(理论篇)】初步理解TCP/IP、Http、Socket.md

    前言 我们平时说的最多的socket是什么呢,实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API).那TCP/IP又是什么呢?TCP/IP是ISO/OS ...

随机推荐

  1. get传递中文产生乱码的解决方式汇总

    1 最基本的乱码问题. 这个乱码问题是最简单的乱码问题.一般新会出现.就是页面编码不一致导致的乱码. <%@ page language="java" pageEncodin ...

  2. jackson中JSON字符串节点遍历和修改

    有些场景下,在实现一些基础服务和拦截器的时候,我们可能需要在不知道JSON字符串所属对象类型的情况下,对JSON字符串中的某些属性进行遍历和修改,比如,设置或查询一些报文头字段. 在jackson中, ...

  3. Ifvisible.js – 判断网页中的用户是闲置还是活动状态

    ifvisible.js 是一个跨浏览器.轻量级的方式,用户检查用户在浏览页面或正在与它进行交互.它可以处理活动状态,如在页面上空闲或活跃.您还可以使用 ifvisible.js 智能设置您的间隔,如 ...

  4. Java Web 三层架构详解

    java 三层架构ssh 一个spring2.5+hibernate3.2+struts2.0组合框架,使用spring的 IoC来管理应用的 所有bean,包括struts2的 action,充分发 ...

  5. 微信公众号里打开链接下载APP

    嵌入这样的代码 <a href="http://a.app.qq.com/o/simple.jsp?pkgname=com.violationquery" target=&q ...

  6. xmpp整理笔记:xmppFramework框架的导入和介绍

    一个将要开发xmpp的项目,建议在项目刚创建就导入框架,这样可以避免一些自己操作失误造成不必要的损失. xmpp中最常用的框架就是 xmppFrameWork 往期回顾: xmpp整理笔记:环境的快速 ...

  7. 小谈KVC中KeyPath的集合运算符

    由于知识点比较简单,这里不再陈述一大堆的原理,直入主题. KVC中的集合运算符有以下三类: 1.简单集合运算符:@avg.@sum.@max.@min.@count (只能用在集合对象中,对象属性必须 ...

  8. Android 调用系统照相机拍照和录像

    本文实现android系统照相机的调用来拍照 项目的布局相当简单,只有一个Button: <RelativeLayout xmlns:android="http://schemas.a ...

  9. java 网络编程基础 1

    关于协议: 应用层网络协议包括:http,ftp,telnet,..... 传送层网络协议:使用socket封装的TCP,或UDP 端口: 用于网络通讯时传输数据时区分当前网络连接是与本机中的哪个应用 ...

  10. 安卓下如何使用JUnit进行软件测试

    软件测试作为程序员必备的一项技能是决定软件开发周期长短以及软件运行成败的关键,可以说好的软件不是代码写得好而是有效的测试决定的.本文将介绍在android下利用eclipse进行开发时如何使用JUni ...