TCP/IP详解 卷1 第二十一章 TCP的超时与重传
21.1 引言
可靠性的保证之一就是超时重传
前面两个超时重传的例子
1) ICMP端口不能到达时,TFTP客户使用UDP实现了一个简单的超时和重传机制,假定5s是一个适当是时间间隔,并每隔5s进行重传
2) 在向一个不存在的主机发送ARP的 例子中,可看到当TCP试图建立连接的时候,在每个重传之间使用一个较长的时延来重传SYN
对于每个连接,TCP管理4个不同的定时器:
1) 重传定时器使用于当希望收到另一端的确认
2) 坚持(persist)定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。22章介绍
3) 保活(keepalive)定时器可以检测到一个空闲连接的另一端何时崩溃或重启。23章介绍
4) 2MSL定时器测量一个连接处于TIME_WAIT状态的时间。
21.1 超时重传的简单的例子
下面是具体的操作:
下面是tcpdump的输出:
19行表示发送方的TCP最终放弃并发送一个复位信号的
可以看到连续重传的时间差,取整后分别为1, 3, 6, 12, 24, 48 和多个64。这种倍乘关系称为指数退避(exponential backoff)。
注意最后放弃的时间,大约是9分组,首次分组(第六行)传输到复位信号传输(19行)。该时间在目前的TCP实现中是不可变的。
// ++++++++++++++++++++++++++++++++++++++
有篇文章:
http://blog.csdn.net/qq_35420908/article/details/72461315
下面这个文章好一点:
https://www.cnblogs.com/menghuanbiao/p/5213722.html
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。
SYN-ACK 重传次数 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
// ------------------------------------------------
21.3 往返时间测量
TCP超时与重传中最重要的部分就是对一个给定连接的往返时间(RTT)的测量。一般这个时间会变,TCP应该跟踪这些变化并相应的改变其超时时间。
(这一段有点难懂,先不看)
21.4 往返时间RTT的例子
并不是所有的报文段都被计时。
大多数源于伯克利的TCP实现在任何时候对每个连接仅测量一次RTT值,。在发送一个报文段时,如果给定连接定时器已经被使用,则该报文段不被计时,
对于每个连接而言,除了这个滴答计数器,报文段中的数据起始序号也被记录下来。当收到一个包含这个序号的确认后,该定时器就被关闭。如果ACK到达时数据没有被重传,则平滑的RTT和被平滑的均值偏差将基于这个新测量进行更新。
21.4.2 RTT估计器的计算
21.4.3 慢启动
21.5 拥塞举例
下面是报文段中数据的起始序号与该报文段发送时间的对比图。
通常代表数据的点将向上和向右移动,这些点的斜率代表传输速率。当这些点向下或向右移动测表示发生了重传。
源于伯克利的TCP实现对收到的重复的ACK进行计数,,当收到第3个时,就假定一个报文段已经丢失并重传自那个序号起的一个报文段。这就是Jacobson的快速重传算法
21.6 拥塞避免算法
拥塞避免算法是一种处理丢失分组的方法。
该算法假定由于分组收到损坏引起的丢失是非常少的(远小于1%),因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞。有两种分组丢失的指示:发生超时和接收到重复的确认。
拥塞避免算法和慢启动算法是两个目的不同,独立的算法、当发生拥塞时,我们希望降低分组进入网络的传输速率,于是可以调用慢启动来做到这一点,在实际中这两个算法通常在一起实现。
这两个算法需要对每个连接都维持两个变量:一个拥塞窗口cwnd,和一个慢启动门限ssthresh。具体工作过程如下:
1) 对于一个给定的连接,初始化cwnd为一个报文段,ssthresh为65535个字节。
2) TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制(发送方感受到网络拥塞的估计),通告窗口是接收方进行的流量控制(与接收方在该该连接上可用的缓存大小有关。)
3) 当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(当前窗口是指cwnd和接收方通告窗口大小的最小值,但是最少为两个报文段)。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动)。
4) 当新的数据被对方确认时,就增加cwnd。但是增加的方法依赖于我们是否正在进行慢启动或拥塞 避免。如果cwnd小于等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生是所处位置的半时候才停止,然后转为执行拥塞避免。
慢启动算法初始值cwnd为1个报文段,此后每收到一个确认就加一。这会使窗口按指数方式增长:发生一个报文段,然后是2个,再然后是4个。(指数增长)
拥塞避免算法要求每收到一个确认时将cwnd增加1/cwnd.这是一种加性增长(additive increase)。我们希望在一个往返时间内最多为cwnd增加一个报文段,然后慢启动将根据这个往返时间中所收到的确认个数来增加cwnd,
术语慢启动并不完全正确。它只是采用了比引起拥塞更慢些的分组传输速率,但是在慢启动期间进入网络的分组数增加的速率仍然是在增加的。只有在的达到ssthresh拥塞避免算法起作用时,这种增长的速率才会慢下来。
// ++++++++++++++++++++++++++++++++++
下面是一篇博客里面的东西:http://blog.csdn.net/smilesundream/article/details/71149434
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢启动门限ssthreah, ssthreah用法如下:
1) 当cwnd < ssthreah:这时候用慢启动算法
2) 当cwnd > ssthreah:使用拥塞避免算法
3) 两者相等时,慢启动和拥塞避免算法任意
拥塞避免算法让拥塞窗口缓慢增长。每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,这样就是线性缓慢增长的。
无论是在慢启动阶段还是拥塞避免阶段,只要发生方判断网络出现了拥塞(没有收到确认或收到重复确认),就把慢启动门限设为出现拥塞时发送窗口大小的一半。然后把拥塞窗口设置为1.算法如下:
// -------------------------------------------------------
21.7 快速重传与快速恢复算法
收到重复的确认ack就需要立即重传丢失的数据报文段,而无需等待超时定时器溢出。接下来执行的不是慢启动算法,而是拥塞避免算法,这就是快速恢复算法。
具体如下:
1) 在收到第三个重复的ACK时,1的报文段。设置cwnd为ssthresh加上3倍的报文段大小
2) 每次收到一个重复的ack,cwnd增加一个报文段 大小,并发送一个分组。
3) 当下一个确认新数据的ack到达时,设置cwnd为ssthresh(第一步设置的值)。这个ack应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ack也应该是对 丢失的分组和收到的第一个重复的ack之间的所有中间报文段的确认。
// 下面是一篇博客的内容。好像有点差异。不过都是快重传和快恢复(cwnd和ssthresh值设的不一样)
http://blog.csdn.net/smilesundream/article/details/71149434
快重传:接收方在收到一个失序的报文后立即发送重复确认,不需要等自己发送数据时捎带确认。
快重传算法规定:发送方只要一连收到3个重复确认就应答立即重传对方 尚未收到的报文段,而不必继续等待设置的重传定时器时间到期。
快速恢复,有以下要点:
1) 发送方连续收到三个重复确认时,执行“乘法减小”算法,把ssthresh门限减半。
2) 不执行慢启动算法,而是执行拥塞避免算法。(具体如何设置cwnd和ssthresh还是看书上的靠谱一点。)
// -------------------------------------------------------------------
21.8 拥塞举例
分析一个快发送快启动的例子:
一个快速重传算法,ssthresh立即设置为当重传发生时正在起作用窗口大小的一半,但是在收到重复ACK的过程中cwnd允许保持增加,这是因为每个重复的ACK 表示一个报文段已经离开了网络,这就是快速恢复算法。
20.9 按每条路由进行度量
较新的TCP实现在啊路由表项中维持许多我们在本章已经介绍过的指标。
当一个TCP连接关闭时,如果已经发送了足够多的数据来获得有意义统计资料,且目的节点的路由表项不是一个默认的表项,那么下列信息就保存在路由表项中以备下次使用:被平滑的RTT、被平滑的均值偏差以及慢 启动门限
当建立一个新的连接时,不论是主动还是被动,如果该连接将要使用的路由表项已经有这些度量的值,则用这些度量来对相应的变量进行初始化。
21.10 ICMP差错
来看看TCP是怎样处理一个给定的连接返回的ICMP的差错。TCP能够遇到的最常见的ICMP差错就是源站抑制,主机不可达,和网络不可达。
当前基于伯克利的实现对这些错误的处理是:、
1) 一个接收到的源站抑制引起拥塞窗口cwnd设置为1个报文段大小来发起慢启动,但是慢启动门限ssthresh没有变化,所以窗口将打开直至它或者开放了所有的通路或者发生了拥塞。
2) 一个接收到的主机不可达或网络不可达实际上都被忽略,因为这个差错都被认为是短暂现象。
当前基于伯克利的实现记录发生的ICMP差错,如果连接超时,ICMP差错被转换为一个更合适的差错码而不是“连接超时 ”。
21.11 重新分组
当TCP超时并重传时,它不一定要重传相同的报文段。相反,TCP允许进行重新分组而发送一个较大的报文段,这有助于提高性能。
在协议中这是允许的,因为TCP是使用字节序号而不是报文段序号来识别 它所要发送的数据和进行确认。
TCP/IP详解 卷1 第二十一章 TCP的超时与重传的更多相关文章
- TCP/IP详解 卷1 第十七章 TCP:传输控制协议
17.2 TCP的服务 TCP提供了一种面向连接的.可靠的字节流服务.两个使用TCP的应用在彼此交换数据之前必须先建立一个TCP连接. TCP通过下列方式来提供可靠性: 1) 应用数据被分割成TCP ...
- TCP/IP详解 卷1 第二十章 TCP的成块数据流
先补充一个知识: 1.停止等待协议:是tcp保证传输可靠的重要途径,"停止等待"就是指发送完一个分组就停止发送,等待对方确认之后,才能继续发送下一个分组 停止等待协议的优点是简单, ...
- TCP/IP详解 卷1 第十八章 TCP的建立与终止
第十八章 TCP的建立与终止 tcpdump Tcpdump可以将网络中传送的数据报完截获下来进行分析.它支持针对网络层.协议.主机.网络或端口的过滤,并提供and.or.not等逻辑语句来帮助你去掉 ...
- TCP/IP详解 卷一(第十一章 UDP:用户数据报协议)
UDP是一个简单的面向数据报的运输层协议. UDP不提供可靠性:它把应用程序传给IP层的数据发送出去,但是并不保证它们能到达目的地. UDP首部的个字段如下图所示
- TCP/IP详解 卷一(第十七章 TCP:传输控制协议)
与UDP协议相比,TCP提供一种面向连接的.可靠的字节流服务. TCP首部 跟UDP一样,TCP数据被封装在一个IP数据报中,下面显示TCP的首部数据格式 每个TCP段都包含源端和目的端的端口号,用于 ...
- 《TCP/IP详解卷1:协议》第3章 IP:网际协议(2)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解 卷1:协议》系列分享专栏
<TCP/IP详解卷1:协议>是一本详细的TCP/IP协议指南,计算机网络历久不衰的经典著作之一. 作者理论联系实际,使读者可以轻松掌握TCP/IP的知识.阅读对象为计算机专业学生.教师以 ...
- 《TCP/IP详解 卷1:协议》第3章 IP:网际协议
3.1 引言 IP是TCP/IP协议族中最为核心的协议.所有的TCP.UDP.ICMP及IGMP数据都以IP数据报格式传输(见图1-4).许多刚开始接触TCP/IP的人对IP提供不可靠.无连接的数据报 ...
随机推荐
- [整理]Linux Crontab命令总结
一.crontab命令的基本介绍 crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab" ...
- highcharts 系统梳理笔记
前言 highcharts最早接触它是在4年前,后来项目中很少用到图表这些东西,就算有也是用echart.他们思路都一样自己去官网上看api即可,构造数据填充节点,没有什么难点,这次是做完手上的工作然 ...
- JAVA基础-File类
一.File类概述 File类是文件和目录路径名的抽象表示形式.File类可以理解为一个文件路径或者文件夹路径的JAVA表现形式,而路径又可以分为绝对路径(是一个固定路径,从盘符开始),相对路径(相对 ...
- spring使用之旅(一) ---- bean的装配
基础配置 启用组件扫描配置 Java类配置文件方式 package com.springapp.mvc.application; import ...
- Golang 网络爬虫框架gocolly/colly 五 获取动态数据
Golang 网络爬虫框架gocolly/colly 五 获取动态数据 gcocolly+goquery可以非常好地抓取HTML页面中的数据,但碰到页面是由Javascript动态生成时,用goque ...
- c++2(循环和递归)
其实编程的朋友知道,不管学什么语言,循环和递归是两个必须学习的内容.当然,如果循环还好理解一点,那么递归却没有那么简单.我们曾经对递归讳莫如深,但是我想告诉大家的是,递归其实没有那么可怕.所谓的递归就 ...
- Docker+Jenkins持续集成环境(3)集成PMD、FindBugs、Checkstyle静态代码检查工具并邮件发送检查结果
为了规范代码,我们一般会集成静态代码检测工具,比如PMD.FindBugs.Checkstyle,那么Jenkins如何集成这些检查工具,并把检查结果放到构建邮件里呢? 今天做了调研和实现,过程如下 ...
- 手把手教你撸一个 Webpack Loader
文:小 boy(沪江网校Web前端工程师) 本文原创,转载请注明作者及出处 经常逛 webpack 官网的同学应该会很眼熟上面的图.正如它宣传的一样,webpack 能把左侧各种类型的文件(webpa ...
- Java多线程编程—锁优化
并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...
- nginx https配置后无法访问,可能防火墙在捣鬼
同事发现nginx配置后https 无法访问,我帮忙解决的时候从以下出发点 1.防火墙未开放443端口 2.配置出错 1 2 3 于是就 netstat -anp 查看防火墙开的端口 发现已经在监听了 ...