深入理解TCP(二)
上一篇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(二)的更多相关文章
- ppp 完全理解(二)【转】
转自:https://blog.csdn.net/tianruxishui/article/details/44057717 ppp 完全理解(二) pppd 协议及代码分析 作者:李圳均 日期:20 ...
- 结合Wireshark捕获分组深入理解TCP/IP协议栈
摘要: 本文剖析了浏览器输入URL到整个页面显示的整个过程,以百度首页为例,结合Wireshark俘获分组进行详细分析整个过程,从而更好地了解TCP/IP协议栈. 一.俘获分组 1.1 准 ...
- 简单理解TCP/IP协议
一.什么是TCP/IP TCP/IP是一个协议族,是因为TCP/IP协议包括TCP.IP.UDP.ICMP.RIP.TELNETFTP.SMTP.ARP.TFTP等许多协议,这些协议一起称为TCP/I ...
- 深入理解TCP建立和关闭连接
建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...
- 深入理解OOP(二):多态和继承(继承)
本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...
- C++ 中类的构造函数理解(二)
C++ 中类的构造函数理解(二) 写在前面 上次的笔记中简要的探索了一下C++中类的构造函数的一些特性,这篇笔记将做进一步的探索.主要是复制构造函数的使用. 复制构造函数 复制构造函数也称拷贝构造函数 ...
- Java 反射理解(二)-- 动态加载类
Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编 ...
- 如何理解TCP的三次握手协议?
• TCP是一个面向链接的协议,任何一个面向连接的协议,我们都可以将其类比为我们最熟悉的打电话模型. 如何类比呢?我们可以从建立和销毁两个阶段分别来看这件事情. 建立连接阶段 首先,我们来看看TCP中 ...
- 【PHPsocket编程专题(理论篇)】初步理解TCP/IP、Http、Socket.md
前言 我们平时说的最多的socket是什么呢,实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API).那TCP/IP又是什么呢?TCP/IP是ISO/OS ...
随机推荐
- SQL数据库: 错误2812 未能找到存储过程 sp_password
SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS OFF GO create procedure sp_password @old sysname ...
- 让.NET 4.0支持TLS1.2协议
The default System.Net.ServicePointManager.SecurityProtocol in both .NET 4.0/4.5 is SecurityProtocol ...
- Linux更改主机名-适用于abuntu
今天复制了个ubuntu虚拟机,于是想更改下主机名以作区别.这是搜到的比较完整的资料,适用abuntu,不过其他linux系统还有待求证. 1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方 ...
- 携带cookie进行数据请求
前端进行数据请求有:普通的ajax(json)请求,jsop跨域请求,cors跨域请求,fetch请求...PC端这些请求方式中,普通的ajax(json)请求和jsop跨域请求是默认携带cookie ...
- 总结的一些微信API接口
本文给大家介绍的是个人总结的一些微信API接口,包括微信支付.微信红包.微信卡券.微信小店等,十分的全面,有需要的小伙伴可以参考下. 1. [代码]index.php <?php include ...
- SyBase Powerdesigner生成数据库详细表
工具: Sybase PowerDesigner 15.1 Microsoft SQL Server 2005 第一步概要设计: 打开PowerDesigner软件,设计“概念数据模型”(Concep ...
- Android中的Touch事件
Android中的Touch事件处理 主要内容 Activity或View类的onTouchEvent()回调函数会接收到touch事件. 一个完整的手势是从ACTION_DOWN开始,到ACTION ...
- yii cookie ,session 操作
一,在Yii中使用session 1,CHttpSession 与原生态php5的session使用差别是,php5使用session_start();$_session['key'] = $valu ...
- List集合概述
上篇总结了Set集合,这回总结下List集合....先来框架图: 一.List集合 List集合代表一个元素有序,可重复的集合,集合中每个元素都有对应的顺序索引.List接口中增加了一些根据索引操作元 ...
- Android ListView添加多种类型的ItemView
一般复杂的ListView都会重写BaseAdapter,通过重用convertView来减少inflate,通过setTag()和ViewHolder改变ItemView的内容. 重写BaseAda ...