【前言】上一篇文章介绍了关于TCP的基础知识,以及建立(释放)连接和滑动窗口的概念。
本篇文章将延续上一篇的思路,继续介绍TCP实现可靠传输的机制。

超时重传

上一篇文章里介绍过TCP采用停止等待协议,即在收到接收方的确认信息后才继续发送下面的数据。
那么如果(在一段时间内)发送方没有收到确认信息,我们便可以认为数据在传输的过程中出了差错,没有顺利传送到接收方。这种情况下,就需要一个“超时重传”的机制了。

TCP 每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段。

那么如何确定重传时间呢?这是TCP最复杂的问题之一。

  • 如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。
  • 但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。

为了得到较为合理的重传时间,TCP 采用了一种自适应算法。

该算法中最关键的就是往返时间(RTT)的测量。
测量往返时间时,由于有的报文经过重传后,无法判断收到的确认报文是重传报文的确认报文还是原报文的确认报文,故采用了Karn算法

  • 在计算平均往返时间 RTT 时,只要报文段重传了,就不采用其往返时间样本。
  • 报文段每重传一次,就把 RTO 增大一些,以弥补重传时间的无法更新。

拥塞控制

在研究拥塞控制的机制前,我们首先需要对“拥塞”的概念有所了解。

拥塞控制的基本概念

什么是“拥塞”

在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种现象称为拥塞 (congestion)。
若网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。

“拥塞控制”与“流量控制”的区别

拥塞控制就是防止过多的数据注入到网络中,使网络中的路由器或链路不致过载;而流量控制往往指点对点通信量的控制,是个端到端的问题(接收端控制发送端)。
拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。
流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

利用拥塞窗口进行拥塞控制

TCP采用基于窗口的方法进行拥塞控制。
TCP发送方维持一个“拥塞窗口”(congestion window),以控制端到端之间未确认的报文数量(拥塞的程度)。

这和之前提到的用于流量控制的“滑动窗口”很像,但是和由接受方决定的“滑动窗口”大小不同,“拥塞窗口”的大小是由发送方决定的。

发送窗口大小不仅取决于接收方公告的接收窗口,还取决于网络的拥塞状况。
真正的发送窗口值为:Min(公告窗口值,拥塞窗口值)

对于拥塞的判断

1、重传定时器超时
由于因传输出差错而丢弃分组的概率是很小的(远小于1%),所以只要出现了超时,就可以猜想网络可能出现了拥塞。

2、收到三个相同的ACK(3 duplicate ACKs)

先假设这么一种情况,B等待A发送首字节序号为3的报文段,给A发送“ack = 3”的确认报文段(ACK),而A在发送过程中出现了丢失,B收到的只有4、5字节的报文段;
此时B给A发送的确认报文中ack字段仍然等于3(因为字节3还没收到);
接着,在B收到字节6后,给A发送的确认报文仍然是“ack = 3”
这就是“收到三个相同ACK”的场景。

因此我们知道,“收到三个相同的ACK”说明有个别报文段在网络中丢失了,预示着网络状况不好,可能会出现拥塞,需要采取措施避免拥塞。

拥塞控制算法

拥塞控制是个麻烦事儿,相关的算法也不少。或者说,多到让人有些头大。

不过不用担心,我们这里只介绍在RFC 5681文件中定义的四种互相紧密关联的算法:

  • 慢开始(Slow Start)
  • 拥塞避免(Congestion Avoidance)
  • 快重传(Fast Retransmit)
  • 快恢复(Fast Recovery)

下面的这张图是一个拥塞控制的过程示例,在学习每一个部分的时候,可以对应图中相应的部分理解。

慢开始

虽然叫“慢开始”,但是它的拥塞窗口(cwnd)增长的速度可一点也不“慢”。
使用慢开始算法后,每收到一个ACK,窗口值就加一;也就是意味着,每经过一个往返时间RTT,拥塞窗口cwnd就加倍。

这里的一个“往返时间”指把拥塞窗口 cwnd 所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。

慢开始门限 ssthresh(Slow Start Threshold)

慢开始门限相当于慢开始“指数式增长”的一个阈值。

  • 当 cwnd < ssthresh 时,使用慢开始算法。
  • 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
  • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。

拥塞避免

拥塞避免的设计思路是让拥塞窗口的增长“慢下来”(相对于慢开始),呈线性增长,或者叫“加法增大”(Additive Increase)。

出现拥塞时

当发现网络出现拥塞时(重传定时器超时),进行以下操作:

  • ssthresh = max(cwnd/2,2)
  • cwnd = 1
  • 执行慢开始算法

快重传和快恢复

就是发送方一连收到 3 个对同一个报文段的重复确认(3-ACK)时,发送方执行快重传和快恢复算法

快重传(Fast Retransmission)
发送方只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而立即进行重传(即“快重传”),这样就不会出现超时,发送方也不就会误认为出现了网络拥塞。
快重传并非取消重传计时器,而是在某些情况下可更早地重传丢失的报文段。

快恢复(Fast Recovery)

  • ssthresh = cwnd/2
  • cwnd = ssthresh
  • 执行拥塞避免算法

    可以留意一下“快恢复”与发现网络出现拥塞时(重传定时器超时)的“‘慢’恢复”的区别。

加法增大,乘法减小(AIMD)

  • 加法增大:拥塞避免阶段,拥塞窗口按照线性规律增大;
  • 乘法减小:当出现超时或3个重复的确认时,就要把门限值设置为当前拥塞窗口值的一半,并大大减小拥塞窗口的数值。

二者的结合就是所谓的AIMD算法。

【后记】
拥塞控制的算法这里只介绍了较为常用的4种,更详细的内容维基百科--TCP congestion control讲得也比较清楚。
接下来的两周可能会比较忙,没有办法更新博客了。最近对3B1B的动画引擎比较感兴趣,可能会写一些相关的内容。
最后,每一条留言都是我的动力(提前祝大家圣诞快乐了

深入浅出图解【计算机网络】 之 【TCP可靠传输的实现2: 超时重传+拥塞控制】的更多相关文章

  1. 计算机网络(9)-----TCP可靠传输的实现

    TCP可靠传输的实现 以字节为单位的滑动窗口 滑动窗口的滑动是以字节为单位的,发送方A和接收方B在TCP三次握手的前两次握手时协商好了发送窗口和接受窗口的大小,发送方A根据B发送来的确认连接报文中标明 ...

  2. TCP可靠传输原理

    停止等待协议 "停止等待"就是发送方在发送完一个分组后停止发送,等待接收方的确认后再继续发送. 超时重传 发送方在等待一定时间后如果还没有收到接收方的确认,此时发送方将认定分组没有 ...

  3. 计算机网络传输层之TCP可靠传输

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105524592 学习课程:<2019王道考研计算机网络> 学习目的 ...

  4. 计算机网络概述 传输层 TCP可靠传输的实现

    TCP可靠传输的实现 TCP的可靠性表现在:它向应用层提供的数据是 无差错的.有序的.无丢失的,简单的说就是:TCP最终递交给应用层的数据和发送者发送的数据是一模一样的. TCP采用了流量控制.拥塞控 ...

  5. TCP可靠传输及流量控制实现原理

    一.为什么TCP是可靠传输? 1. 停止等待协议 通过确认与超时重传机制实现可靠传输 在发送完一个分组后,必须暂时保留已发送的分组的副本. 分组和确认分组都必须进行编号. 超时计时器的重传时间应当比数 ...

  6. 运输层6——TCP可靠传输的实现

    目录 1. 以字节为单位的滑动窗口 2. 超时重传时间的选择 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3- ...

  7. TCP可靠传输的实现

    TCP可靠传输的实现 1.概述      为方便描述可靠传输原理,假定数据传输只在一个方向上进行,即A发送数据,B给出确认 2.以字节为单位的滑动窗口      TCP的滑动窗口是以字节为单位的.为了 ...

  8. TCP可靠传输的工作原理

    TCP可靠传输的工作原理 一.停止等待协议 1.1.简介 在发送完一个分组后,必须暂时保留已发送的分组的副本. 分组和确认分组都必须进行编号. 超时计时器的重传时间应当比数据在分组传输的平均往返时间更 ...

  9. TCP 可靠传输与流量控制的实现

    TCP 可靠传输与流量控制的实现 一.TCP可靠传输的实现 现在所讲的可靠传输是根据之前所说的可靠传输原理的实现,是现实中应用的技术. 1.1.以字节为单位的滑动窗口 如图A端一份文件分为了多个字节, ...

随机推荐

  1. javaweb+spring 项目集成异常的处理

    在web项目开发中,一个系统应该要考虑到异常情况的处理,并且应该当异常发生时应该需要记录相应的异常日志,对于用户而言则不能直接抛出异常,需要考虑到用户的体验: 以下就介绍基于spring框架的基础上的 ...

  2. 一对一关联查询注解@OneToOne的实例详解

    表的关联查询比较复杂,应用的场景很多,本文根据自己的经验解释@OneToOne注解中的属性在项目中的应用.本打算一篇博客把增删改查写在一起,但是在改的时候遇到了一些问题,感觉挺有意思,所以写下第二篇专 ...

  3. python3异常处理 try

    一. 简介 在编程过程中为了增加友好性,在程序出现Bug时一般不会直接将错误信息展示给用户,而是提供一个友好的输出提示. 二. 使用 1.异常基础 常用结构: try: pass except Exc ...

  4. 【HDU5126】 stars k-d树

    题目大意:有$m$个操作,分两种:在指定三维坐标内加入一个点,询问指定空间内点的数量. 其中$m≤5*10^{4},1≤x,y,z≤10^9$ 这题几乎就是裸的$k-d$树啊.我们动态维护一棵$k-d ...

  5. Linux grep命令详解[备份]

    linux grep命令 1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expressi ...

  6. css设置:图片文字等不能被选择

    -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;

  7. 四则运算2及psp0设计

    随机生成运算式,要求: 1.题目避免重复. 2.可定制(数量/打印方式). 3.可以控制一下参数. 要求:是否有乘除法,是否有括号,数值范围,加减有无负数,除法有无余数. 刚开始看到这样一个题目感觉还 ...

  8. Android 开发工具类 07_ScreenUtils

    获得屏幕相关的辅助类: 1.获得屏幕高度: 2.获得屏幕宽度: 3.获得状态栏的高度: 4.获取当前屏幕截图,包含状态栏: 5.获取当前屏幕截图,不包含状态栏. import android.app. ...

  9. Python 基础语法——数字和表达式(包含数学上的一些函数)

    >>> 2+2 4 >>> 1/2 0 >>> 1.0/2.0 0.5 >>> 1/2.0 0.5 >>> 1 ...

  10. 原生js动态添加style,添加样式

    原生js动态添加style,添加样式 第一种 var style="[assign-url='"+str+"']{display:initial}"; var ...