计算机网络 | 传输层 | TCP&UDP |可靠传输

文章目录

传输层(对网络层提供的服务的加强与改善,并提供给应用层)

一、概述和传输层服务

1.传输服务和协议

这里在提一嘴,TCP传输的报文是没有边界的,也就是说信息的合理分段是应用层需要自己做的事情
在这里插入图片描述

  • 提供的服务

传输层向上提供的服务:为运行在不同主机上的应用进程提供以报文为单位逻辑通信

  • 传输协议运行在端系统

发送方:将应用层的报文分成报文段,然后传递给网络层
接收方:将报文段重组成报文,然后传递给应用层

  • 传输协议

TCP和UDP,他俩都是建立在IP协议的基础上来完成的
在这里插入图片描述

2.传输层 vs. 网络层

  • 前提

我们知道每一层的逐渐向上都是对下层服务的提升与改善,那么传输层对网络层所提供的服务进行了怎么样的提高并给应用层提供了怎样优质的服务

  • 网络层服务(主机之间逻辑通信)

  • 传输层服务(进程间的逻辑通信)

    依赖于网络层的服务:延时、带宽
    并对网络层的服务进行增强:数据丢失、顺序混乱、加密
    同时可以引出源端和目标端的复用与解复用,即每个TCP或UDP实体即是源端也可以是目标端,也就是说复用与解复用就是角色之间的转换并且重复使用

  • 类比网络层和传输层之间的角色

即这12个小孩的信被家里面老大封装(复用)成一个邮包进行邮政公司运送(网络层传输),每个信封上都有源端和目标端,等到目标端那个家的老大进行拆包(解复用)说这个是谁的,那个是谁的
在这里插入图片描述

  • 注意

有些服务是可以加强的:不可靠 -> 可靠、安全;但有些服务是不可以被加强的:带宽,延迟

二、多路复用/解复用

在这里插入图片描述

1.TCP

在这里插入图片描述

如果是多线程的话,可能发送给同一个进程的不同线程
在这里插入图片描述

2.UDP

不同客户端的信息发送给目标端的端口号一致,那么就是说这些信息都是给这个端口对应的应用
在这里插入图片描述在这里插入图片描述

三、无连接传输:UDP(User Datagram Protocol:用户数据报协议)

1.概述

  • “尽力而为”的服务,报文段可能丢失、送到应用进程的报文段乱序

    即对于IP网络层的改进也就是只有添加了进程到进程之间的通信

  • 无连接

    UDP发送端和接收端之间没有握手、每个UDP报文段都被独立地处理

  • 多用于网络流媒体即对信息丢失不敏感,对速率敏感的应用适合

  • 想要在UDP上进行可靠传输就要在应用层下功夫了

1.1 为什么要有UDP(前面也简略提到过)
  • 不建立连接(会增加延时)
  • 简单:在发送端和接收端没有连接状态
  • 报文段的头部很小(开销小)
  • 无拥塞控制和流量控制:UDP可以尽可能快的发送报文段

    应用——>传输的速率 = 主机——>网络的速率

2.UDP报文段的格式

从图中可以看到当头部字节数越大,那么应用程序数据的容量就越小即承载量就越小
在这里插入图片描述

3.UDP校验和

  • 目的:检测在被传输报文段中的差错 (如比特反转)
3.1 发送方
  • 将报文段的内容视为16比特的整数
  • 校验和:报文段的加法和(1的补运算)
  • 发送方将校验和放在UDP的校验和字段
3.2 接收方
  • 计算接收到的报文段的校验和
  • 检查计算出的校验和与校验和字段的丙容是否相等:

    不相等:检测到差错
    相等:没有检测到差错,但也许还是有差错(残存错误:就是错的离谱到校验和竟然和对的是一样的)

3.3 例子

在这里插入图片描述

四、可靠数据传输(RDT)的原理

1.前言

  • 如果有序号的存在,那么一定要约定同步(值相同),也就是序号同步开始或结束

  • rdt在应用层、传输层和数据链路层都很重要

  • 是网络Top 10问题之一

  • 信道的不可靠特点决定了可靠数据传输协议( rdt )的复杂性

  • 渐增式地开发可靠数据传输协议( rdt)的发送方和接收方

  • 只考虑单向数据传输

    但控制信息(例如对方接收到可能会返回一些信息等)是双向流动的,意思就是将双向变为两个单向

  • 双向的数据传输问题实际上是2个单向数据传输问题的综合

  • 使用有限状态机(FSM如下图)描述发送方和接收方
    在这里插入图片描述

2.RDT版本变迁

  • 概述

我们先来介绍一下,可靠传输的发展,没有握手机制那时候

  1. RDT 1.0:最简单的可靠传输,就是下层信道完全可靠即在可靠信道上的可靠传输,下层通道可能出错,但是无法进行比特差错的校验
  2. RDT 2.0具有比特差错的通道,因为下层可能出错,所以我们需要校验和来检测,然后接收方返回ACK(正确接收)或NAK(错误接收),此时要求发送端进行发送数据的备份以及重发
  3. RDT 2.1修复了ACK和NAK本身出错的错误,让传输的包带上序号,只需0和1两种,虽然接收方不知道是否接收成功,但是可以看下一次传过来的包序号,重复则出现错误
  4. RDT 2.2此时将确认冗余信息给简化,将NAK去除;将ACK带上序号,同样只需要0和1,出错就发跟上次一样的ACK和序号
  5. RDT 3.0:将重发机制改为自动触发的机制,即超时重传
  • RDT的缺点

就是无法利用链路的容量,每次只发一个,增大发送的数量也会造成混乱编码需要增加,而下面要介绍的流水线,那一次性发送多个未经确认的分组**

3.滑动窗口(slide window)协议

3.1 概述
  • 发送缓冲区
  • 形式:内存中的一个区域,落入缓冲区的分组可以发送
  • 功能:用于存放已发送,但是没有得到确认的分组
  • 必要性:需要重发时可用
  • 发送缓冲区的大小:一次最多可以发送多少个未经确认的分组
  • 停止等待协议=1
  • 流水线协议>1,合理的值,不能很大,链路利用率不能够超100%
  • 发送缓冲区中的分组
  • 未发送的:落入发送缓冲区的分组,可以连续发送出去;
  • 已经发送出去的、等待对方确认的分组:发送缓冲区的分组只有得到确认才能删除
3.2 为什么要引入以及与内部概念与协议的联系
3.2.1 why

我们知道RDT虽然很优秀但也有缺点,有了解决我们就有了流水线协议,而流水线协议又分为两种

3.2.2 图示联系

下面一些名词稍安勿躁,接下来就会讲解
在这里插入图片描述

3.3 发送窗口(sending-window)及接收窗口

先来看看发送窗口移动的方式
在这里插入图片描述

3.3.1 概述
  • 发送窗口:发送缓冲区内容的一个范围

那些已发送但是未经确认分组的序号构成的空间

  • 发送窗口的最大值 <= 发送缓冲区的值
  • 一开始:没有发送任何一个分组

后沿=前沿,之间为发送窗口的尺寸=0

  • 每发送一个分组,前沿前移一个单位

下图就是发送窗口为空集,发送缓冲区为0.1.2.3.4
在这里插入图片描述

3.3.2 前沿的移动
  • 发送窗口前沿移动的极限:不能够超过发送缓冲区

由上图看到就是发送窗口的前沿不能超过绿色的部分

在这里插入图片描述

3.3.3 后沿的移动

发送窗口后沿移动

  • 条件:收到老分组的确认
  • 结果:发送缓冲区罩住新的分组,来了分组可以发送
  • 移动的极限:不能够超过前沿
3.3.4 发送窗口的移动

发送窗口后沿移动

  • 条件:收到老分组(后沿)的确认
  • 结果:发送缓冲区罩住新的分组,来了分组可以发送
  • 移动的极限:不能够超过前沿
    在这里插入图片描述
3.3.5 接收窗口(receiving window) = 接收缓冲区(注意这里是接收窗口)
  • 接收窗口用于控制哪些分组可以接收;

只有收到的分组序号落入接收窗口内才允许接收。若序号在接收窗口之外,则丢弃;

  • 接收窗口尺寸Wr = 1,则只能顺序接收
  • 接收窗口尺寸Wr > 1,则可以乱序接收

但提交给上层的分组,要按序

  • 例子:Wr = 1,在0的位置;只有0号分组可以接收;向前滑动一个,罩在1的位置,如果来了第2号分组,则丢弃,并且给顺序到来最大序号分组确认,这个例子中即要给0一个ACK=0;往后如果来了3.4.5等等只要2号分组没收都要做这两个动作,一是丢弃,二是确认消息
    在这里插入图片描述
3.3.6 接收窗口的滑动和发送确认
  • 滑动:
  • 低序号的分组到来,接收窗口移动;
    在这里插入图片描述
  • 高序号分组乱序到,缓存但不交付(因为要实现rdt,不允许失序),不滑动
    在这里插入图片描述
  • 发送确认:
  • 接收窗口尺寸 = 1;发送连续收到的最大的分组确认(累计确认〉
  • 接收窗口尺寸 > 1;收到分组,发送那个分组的确认(非累计确认)
3.3.7 正常情况下两个窗口的互动

发送窗口

  • 有新的分组落入发送缓冲区范围,发送->前沿滑动
  • 来了老的低序号分组的确认->后沿向前滑劫->新的分组可以落入发送缓冲区的范围

接收窗口

  • 收到分组,落人到接收窗口范围内,接收
  • 是低序号,发送确认给对方

发送端上面来了分组 -> 发送窗口滑动 -> 接收窗口滑动 -> 发确认

3.3.8 异常情况下两个窗口的互动(GEN协议下)

发送窗口

  • 新分组落入发送缓冲区范围,发送->前沿滑动
  • 超时重发机制让发送端将发喾窗口中的所有分组发送出去
  • 来了老分组的重复确认 -> 后沿不向前滑动丰新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)

接收窗口

  • 收到乱序分组,没有落入到接收窗口范甩内,抛弃,在接收方不被缓存!
  • (重复)发送老分组的确认,累计确认
3.3.9 异常情况下两个窗口的互动(SR协议下)

发送窗口

  • 新分组落入发送缓冲区范围,发送->前沿滑动
  • 超时重发机制让发送端将超才的分组重新发送出去
  • 来了乱序分组的确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲飞有新的分组可以发送)

接收窗口

  • 收到乱序分组,落入到接收窗范围内,接收
  • 发送该分组的确认,单独确认
3.3.10 GBN协议和SR协议的异同

相同点

  • 发送窗口>1
  • 一次能够可发送多个未经确认的分组

不同点

  • GBN∶接收窗口尺寸=1

接收端:只能顺序接收
发送端:从表现来看,一旦一个分组没有发成功,如:0,1,2,3,4∶假如1未成功,234都发送出去了,要返回1再发送;GB到1,然后把1以后发送的包括1在全部发送一遍

在这里插入图片描述

  • SR:接收窗口尺寸>1

接收端:可以乱序接收;这里如果是顺序发送,并且顺序接收会将确认接收到的封装成一个大的向上层交(在上层解封装),当回传确认消息是ACK的编号只需要这个这个大的封装信息中第一个序号,但如果发送过程中某个编号段出现丢失错误,当接收端的后沿是这个错误编号时,后面成功接收的会等待这个错误编号的计时器超时重传并成功接收再一起封装!
发送端:发送0,1,2,3,4,一旦1未成功,2,3,4,己发送,无需重发,选择性发送1

在这里插入图片描述

3.4 总结(GBN和SR协议)

在这里插入图片描述

五、面向连接的传输:TCP(Transmission Control Protocol)

在这里插入图片描述

1.概述

  • 点对点:

    一个发送方,一个接收方

  • 可靠的、按顺序的字节流:

    没有报文边界

  • 管道化(流水线):

    TCP拥塞控制和流量控制设置窗口大小

  • 发送和接收缓存

  • 全双工数据:

    在同一连接中数据流双向流动
    MSS:最大报文段大小
    MSS就是在应用层的传下来的字节流信息被分成一定数量的段
    在这里插入图片描述

  • 面向连接:

    在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量

  • 有流量控制:

    发送方不会淹没接收方

1.1 TCP报文段结构
  • 序号:就是把字节流切成一个个MSS,每个MSS根据上个MSS形成的偏移量,ACK等于序号时,实际上时序号之前的全部但不包括序号所代表的数据
  • 确认号:期望从另一方收到的下一个字节的序号;累积确认

在这里插入图片描述

1.1.1 TCP序号和确认号

在这里插入图片描述

2.TCP往返延时(RTT)和超时(下面还会再复习一遍)

2.1 前言

在上一节可靠传输的协议我们说到,对于信息的丢失或错误会采取超时重发的策略,那么超时时间的设置又会影响到效率等一系列十分重要的速度,所以我们需要精准设置

  • 怎样设置TCP超时?

比RTT要长但RTT是变化的
太短:太早超时,不必要的重传
太长:对报文段丢失,反应太慢,消极

  • 怎样估计RTT?
  • SampleRTT:测量从报文段发出到收到确认的时间
    如果有重传,忽略此次测量
  • SampleRTT会变化,因此估计的RTT应该比较平滑
    对几个最近的测量值求平均,而不是仅用当前的SampleRTT
  • EstimatedRTT

因为SampleRTT会变化无常,所以我们的参考要以平均值为准,可以看到公式,越靠后前面的采样值影响就越小
在这里插入图片描述

2.2 设置超时

形容的可以理解为:这个超时时间设置的十分保守,大概会等待四个间隔的时间也就是一次首次确认+三次冗余确认,四次以后还没来就大概率信息丢失
在这里插入图片描述

3.TCP如何向上层提供可靠的数据传输(RDT)

3.1 概述
  • TCP在IP不可靠服务的基础上建立了rdt
  • 管道化的报文段:GBN or SR
  • 累积确认(像GBN)
  • 单个重传定时器(像GBN)
  • 是否可以接受乱序的,没有规范
  • 通过以下事件触发重传
  • 超时(只重发那个最早的未确认段:SR)
  • 重复的确认;例子:收到了ACK50,之后又收到3个ACK50
  • 首先考虑简化的TCP发送方:
  • 忽略重复的确认
  • 忽略流量控制和拥塞控制
3.2 接收方

从应用层接收数据:

  • 用nextseq创建报文段
  • 序号nextseq为报文段首字节的字节流编号
  • 如果还没有运行,启动定时器
  • 定时器与最早未确认的报文段关联
  • 过期间隔:TimeoutInterval

超时:

  • 重传后沿最老的报文段
  • 重新启动定时器

收到确认:

  • 如果是对尚未确认的报文段确认
  • 如果后沿已经移动到前沿的位置且还有没有确认这时定时器是要被关闭的
  • 更新已被确认的报文序号
  • 如果当前还有未被确认的报文段,重新启动定时器

在这里插入图片描述

3.3 超时重传(累计确认+期待)
  • 超时时间(RTO)的计算与动态改变

先介绍三个变量:RTT(Sample):往返时间样本值、RTT(Dev):RTT的平均值、RTO(重传计时器)

  • 首次重传,由于没有前面的参照,RTTS就取值本次的RTT,然后RTTD为RTTS的一半,RTO=RTTS+4RTTD
  • 今后重传及动态变化:首先得到本次RTT的时间,引入两个常量α取1/8,β取1/4然后新的RTTS=(1-α)×(旧的RTTS)+α×(本次RTT样本);新的RTTD=(1-β)×(旧的RTTD)+β×|RTTS - 本次RTT样本|,RTO = RTTS+4RTTD
    在这里插入图片描述
  • 快速重传

当收到三个相同的ACK报文段时,就重传丢失的数据文段,而无需等待超时定时器溢出;例如1~5传输,1,3,4,5,到达,服务器发了三个确认序号都为2的确认报文,那么我们直接重传,但是有个问题是只重传2还是2之后的都重传,那么就有了流水线协议了,前面两种解决方式也就对应了两种流水线协议

  1. 回退N步协议(GBN):未收到之后的全部重发,即我们要求为顺序接收
  2. 选择性重发协议(SR):只重发未收到的,这个就可以乱序接收(但是交给上层的数据还是窗口中完成的顺序数据哦),对于老分组进行单独确认,这个的实现是基于SACK选项,在报文头部的可选项中,它可以将接受缓冲区的地图发送给发送⽅即接收的范围然后就可以知道那些重传了
  • 累计确认

对于发送多个未确认分组后,如果确认首个报文的确认报文未成功达到,那么发送方肯定会重发首个报文,此时首个后面的报文全部成功到达,那么重发报文后的确认报文的ACK值是后面全部达到中的最大序号值,即累计确认

4.TCP 流量控制

  • 概述

接收方控制发送方,不让发送方发送的太多、太快以至于让接收方的缓冲区溢出

4.1 具体控制
  • 接收方在其向发送方的TCP段头部的rwnd(空闲)字段“通告(称为捎带技术,即附带着告诉你这个信息)”其空闲buffer大小
  • RcvBuffer大小通过socket选项设置(典型默认大小为4096字节)
  • 很多操作系统自动调整RcvBuffer
  • 发送方限制未确认(“in-flight”)字节的个数 ≤ 接收方发送过来的rwnd

  • 保证接收方不会被淹没
    在这里插入图片描述

  • 概述

接收方控制发送方不让发送方发的太多太快让接收方的缓冲区溢出

  • 具体操作

就是接收方发送确认报文时会带自己的窗口大小(即空闲的缓冲大小),于是发送端不会发送超过这个值的数据,对于接收方一旦面临超过数据移除下一次发送确认则会发送一个更小的

  • 窗口关闭的死锁

接收方发过来的确认报文中的窗口大小为0时,窗口就关闭了发送端无法发送新的过去,直到窗口变成非0时才能开始接收;但此时如果接收端发送自己非0的ACK在网络中丢失就会产生死锁

  • 死锁的解决

TCP为每个连接建立非0计时器,只要连接的一方接收到对方的0窗口通知,就会启动计时器

  • 超时中如果回传了非0的ACK通知,则继续发送
  • 超时后则主动发送询问通知,回传的ACK通知窗口还是0则重置计时器
    ,如果不是0则继续发送
  • 糊涂窗口综合症的解决

糊涂窗口综合症是指:简而言之就是接收方的窗口不能有一点点空间就发送非0ACK,发送方不要就发送满足小窗口的报文段

  • 接收方:接收方要等到接收窗口变得大一点在通知以及在快要变0时就回应窗口为0的报文:当小于MSS或者缓存的一半时就会发送0窗口通知
  • 发送方:约束发送方就是报文长度一定是一个MSS,发送至少是接收方窗口一半的报文段(Nagle算法)
4.2 缓存中可用空间的计算

用最近收到的字节 - 最近被读的字节 = 在buffer中缓冲的字节(就是还没来得及读的字节)
总的缓冲区 - 在buffer中缓冲的字节 = 空闲的 = RcvWindow(这个字段就就是TCP报文结构中很重要的一个字段)

在这里插入图片描述

5.TCP连接管理(三次握手、四次挥手)

在正式交换数据之前,发送方和接收方握手建立通信关系

  • 同意建立连接(每一方都知道对方愿意建立连接)
  • 同意连接参数
    在这里插入图片描述
5.1 概述
  • 在网络中,2次握手建立连接总是可行吗?
  • 变化的延迟(连接请求的段没有丢,但可能超时)
  • 由于丢失造成的重传(e.g.req_conn(X))
  • 报文乱序
  • 相互看不到对方
5.2 二次握手

在这里插入图片描述

  • 二次握手的失败场景
  1. 在两次握手中又会以下难以处理的情况:一是如果在确认请求的发送过程中请求端的超时器超时重新发了一个请求这个请求到达时间是连接已经建立完成后,那么客户端就不会在建立了,此时服务器还在维护这个后来的请求,称为半连接
    在这里插入图片描述
  1. 二是在一的基础上,又发生了数据超时重传,数据的重新发送而且还被成功接收当作新的数据
    在这里插入图片描述
5.3 三次握手

我们先必须复习一下TCP报文段的格式

TCP会处理HTTP传下来的报文,如果超过MSS(最大报文长度)会分段

  • 和UDP一样,源端口和目标端口
  • 32位的序号字段和确认序号字段
  • 16位的串口大小
  • 4位的首部字段即数据偏移,首部字段长度是可变的
  • 9位的标志位:标志现在连接是什么状态
  • 16 位的紧急数据指针字段,当紧急数据存在并给出指向紧急数据尾的指针的时候, TCP 必须通知接收端的上层实体 。
    在这里插入图片描述
  • 标志位的总结
  • URG:紧急指针有效
  • ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建⽴连接时的 SYN 包之外该位必须设置为 1 。
  • PSH:接收方应该尽快将这个报文段交给应用层。
  • RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
  • SYN:该位为 1 时,表示希望建⽴连接,并在其「序列号」的字段进⾏序列号初始值的设定。
  • FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双⽅的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。
  • 序号的总结

之所以需要序号是因为TCP把传输的数据看做了有序的字节流,按顺序发送就需要每个字节上都标上编号,序号是每一个报文段中首字节的编号;在初始化时是随机而得的

  • 接收方可以取出重复数据
  • 接收方可以根据序号按序接收,因为序号就是表示发送方的当前包的其实数据序列号
  • 发了那些,没有发那些都知道
  • 确认号总结

在TCP中发送方需要接收方接收成功后发送一个接收成功的消息,叫做确认应答(ACK);与序号结合就知道下一次该从那个序号开始了;例如接收了0~5的和8~9的,那么下一次的确认号就会为6,说明下次从6开始发

  1. 第一次握手
  • 客户端初始化自己的序号(client_lsn)将该序号放到首部序号字段中,同时把SYN的标志位置为1,该报文段称为SYN报文段
  • 被封装在IP数据报中,发送给服务器,该报文段不含任何业务数据,发送完之后客户端处于SYN-SENT状态
  1. 第二次握手
  • 服务器在收到SYN报文段后,会为该连接分配TCP缓存和变量,并随机初始化自己的序号(server_isn),将此序号填入自己首部【序号字段】中;然后把TCP首部的【确认字段】填入客户端序号+1(client_lsn+1),接着将SYN和ACK标志位置为1,该报文段称为SYNACK报文段
  • 最后把该报文发给客户端,报文不含任何业务数据,之后服务器进入SYN-RCVD状态
  1. 第三次握手
  • 客户端收到SYNACK报文段后,客户端也为该连接分配缓存和变量,还要向服务器回应一个应答报文,首先该应答报文TCP首部字段ACK置为1,其次【确认序号】填入服务器序号+1(server_isn+1),自己的【序号字段】为服务器传过来的同理连接报文中的【确认字段】(client_lsn+1),最后发送报文段
  • 这段报文段可能就携带业务数据了,只有这一次。之后客户端处于ESTABLISHED 状态,服务器收到客户端的报文段也进入ESTABLISHED 状态
  • 为什么是三次而不是两次,原因有二:
  1. 避免旧连接造成混乱和资源浪费
  • 由于网络延迟一客户端超时重发许多个SYN报文段,当一个旧的报文段先于新的报文段到达服务器
  • 这时服务器会返回一个SYNACK报文段,根据客户端上下文,客户端维护的序号跟返回报文段的确认序号是对不上的;即客户端的序号是根据最新的请求的
  • 根据以上判断为历史连接,发送RST标志位为1的报文段给服务器,表示出现异常终止这一次连接
  • 如果判端不是历史连接,则发送ACK报文建立连接

但如果是两次连接:

  • 你就会发现客户端不能判断当前是否为历史连接
  • 服务器也不清楚客户端是否收到了自己发送的ACK应答报文,所以每收到一个SYN报文段都要去申请资源,
  • 如果网络拥塞会发送很多个SYN,维护无数个半连接,造成不必要的浪费
  1. 同步双方序号

由于TCP是全双工,双方自己维护序号,序列号是可靠传输的一个关键因素

  • 当客户端发送SYN报文时必须携带自己的初始化的序号,需要客户端返回一个SYNACK报文,就可以根据自己的序号和返回的报文段进行比对,比对表示SYN报文已经被服务器成功接收了
  • 反之服务器发送初始序号时也需要得到客户端的应答
  • 第 2 次握手传回了 ACK,为什么还要传回 SYN?

因为时双全工猪鼻

5.4 四次挥手
  • 概述

TCP通过四次挥手断开连接,双方都可以主动断开连接,断开连接后主机中的资源将被释放。

  • 流程
    1. 第一次挥手:客户端进程想要关闭连接,会发送一个TCP首部标志位FIN被置为1的报文段,初始化序号填入首部序号字段,之后客户端进入FIN_WAIT_1状态
    2. 第二次挥手
      • 服务器收到后,向客户端发送ACK确认报文段,值为第一次挥手发来的序号+1,接着服务器进入CLOSED_WAIT状态
      • 客户端收到后进入FIN_WAIT_2状态,此时客户端没有要发送的东西了
    3. 第三次挥手:等待数据处理完,也想客户端发送FIN报文段,首部序号字段初始化,之后服务器进入LAST_ACK状态,
    4. 第四次挥手
      • 客户端收到服务器的FIN报文后,回一个ACK应答报文(内容同理为收到的序号+1),之后进入TIME_WAIT状态
      • 服务器收到ACK报文后,就进入CLOSED状态,至此服务器已经完成连接的关闭
      • 客户端在经历2MSL时间后,自动进入CLOSED状态,至此客户端也完成了连接的关闭
  • 流程图

在这里插入图片描述

  • 为什么挥手需要四次呢
  • 因为服务器在在发送ACK后,通常还需要等待完成数据的发送和处理,才能关闭连接,所以这部分完成的时间需要服务器自己决定所以需要自己多一次的挥手
  • 为什么需要最后的 TIME_WAIT 状态?
  • 防止旧连接的数据包:如果没有等待时间,又有新的TCP连接复用了这个连接的端口,服务器没有收到ACK后,又会重发FIN,此时造成混乱
  • 保证双方的连接都可以正确关闭:收到最后一个ACK就关闭状态,服务器就关闭;没有收到,则重发FIN报文段等待新的ACK
  • 为什么 TIME_WAIT 等待的时间是 2MSL?

MSL:是报文段的最大生存时间,即任何报文段被丢弃前在网络内的最长时间。在Linux中一个MSL为30s
客户端在收到FIN报文后,发送ACK报文,如果服务器没有接收到发过来的ACK,就会重发FIN报文,所以发送ACK和对方发送FIN刚好为2MSL,

  • 如果超过没有再次收到FIN那么服务器就关闭了
  • 没有超过收到了FIN报文,重新计时
  • TIME_WAIT 过多是为什么,有什么危害,如何优化?
  • 因为客户端建立了大量短连接,造成大量TIME_WAIT
  • 占用系统资源,一个TIME_WAIT 也就是一个连接的文件描述符占4KB
  • ①.打开net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项;可以快速复用 TIME_WAIT 的套接字,打开时间戳支持,将过期的报文段丢弃,防止旧的报文段导致错误。②.使用 SO_LINGER 直接用 RST 报文强制关闭连接。

对于快速回收和复用而言:快速回收是有害的,对于建立的连接因为迟到的数据包引起异常从而关闭;或对于之间的连接直接被劫持。但复用是无害的,可以节省资源

  • 那 CLOSE_WAIT 过多是为什么,有什么危害,如何优化?
  • CLOSE_WAIT 过多表示服务器在接收到关闭请求后,没有立马的做出相应并关闭请求,会导致连接无法释放占用文件描述符资源,问题一定出现在程序内部,而不是通过调操作系统的参数解决。
  • 服务器有大量的CLOSE_WAIT 未释放,而客户端也会源源不断的发送新的请求,这样文件描述符的数量激增,CPU或内存飙高;
  • 所以一般向Linux系统来说一个进程所持有的文件描述符都是有限的

六、拥塞控制原理

1.拥塞概述

  • 非正式的定义:"太多的数据需要网络传输,超过了网络的处理能力“
  • 与流量控制不同(我到你的数据量需要控制)
  • 拥塞的表现:
  • 分组丢失(路由器缓冲区溢出)
  • 分组经历比较长的延迟(在路由器的队列中排队)
  • 网络中前10位的问题

2.拥塞是什么

  • 延迟大,因为流量强度已经无限接近于一,如果在某个关键节点不加控制会出现断崖式的速率减弱;
  • 并且数据存在部分丢失,丢失就要重传为了使网络达到理想的状态有时需要发更多的数据(比如发送1,但接收只能0.8,那我们就只能发1.2来弥补有效接收的部分);
  • 在网络拥塞时会重传许多没有必要的数据,因为在排队的时候一不小心就超出了超时器的时长,那么就会重发重复的,实际上这个数据只是在排队并没有丢失
  • 当设备足够多在相互传递数据时,可能会造成类似死锁的状态,全在等着前面走,释放速率,前面的又在等着前面的前面反反复复
  • 当处于链路上游马上到达的数据如果出现了丢失,此时是非常浪费速率的一件事

3.拥塞控制的方法

3.1端到端拥塞控制
  • 没有来自网络的显式反馈
  • 端系统根据延迟和丢失事件推断是否有拥塞
  • TCP采用的方法
3.2 网络辅助的拥塞控制
  • 路由器提供给端系统以反馈信息
  • 单个bit置位,显示有拥塞(SNA,DECbit,TCP/IP ECN,ATM)
  • 显式提供发送端可以采用的速率

4.ATM ABR 拥塞控制

ATM:类似于路由器来交换信元的节点设备

4.1 ABR(available bit rate)
  • "弹性服务”
  • 如果发送端的路径“轻载”

发送方使用可用带宽

  • 如果发送方的路径拥塞了

发送方限制其发送的速度到一个最小保障速率上

4.2 信元
  • 信元是处于字节与报文之间的一种传输形式
  • 分为有数据信元和资源管理信元(资源管理信元是插入在数据信元之中)
4.2.1 RM(资源管理)信元
  • 由发送端发送,在数据信元中间隔插入
  • RM信元中的比特被交换机设置(网络辅助”),标志位改变后都会从目标端反转回源端(此时源端是知道路径上的拥塞情况)来进行各种措施来缓解
  • NI bit: no increase inrate(轻微拥塞)速率不要增加了,标志位0或1
  • CI bit: congestion indication拥塞指示,标志位0或1
  • 发送端发送的RM信元被接收端返回,接收端不做任何改变

七、TCP拥塞控制

1. 拥塞控制

  • 概述

与流量控制的角度不一致,拥塞控制不聚焦于两个端系统的交互,而是放眼整个网络,防止网络的瘫痪,防止发送方突然发送大量的数据;此时控制发送方的数据量引入一个拥塞窗口的概念

  • cwnd

发送方维护的一个变量,根据拥塞程度动态变化(拥塞变小、反之变大),发送窗口是拥塞窗口和接受窗口较小的值。

  • ssthresh

开始拥塞控制的cwnd阈值;

  • 在初始系统中,该值是一个大概估计发送拥塞的拥塞避免值(默认为65535字节),即cwnd触发到ssthresh就开始拥塞避免,每次加法增加窗口值
  • 往后运行时,当发现由于重发三次ACK或者超时后就会把该值设置为发生时cwnd的一半
  • 拥塞解决方式:慢启动

当网络连接处于初始状态时,将拥塞窗口会设置成1MSS,之后每接收一个ACK,拥塞窗口的cwnd就增加一个MSS,然后窗口在后期会以指数级的速度向上增加直到达到慢启动的阈值(ssthresh:65535字节)

  • 拥塞解决方式:拥塞避免

拥塞避免要求每收到一个ACK,cwnd的值增加1 / cwnd(一般就是增加一个MSS)。与慢启动的指数增加比起来,这是一种加性增长

  • 拥塞解决方式:快速恢复

将阈值设置成cwnd的一半然后cwnd设置成阈值+3,重传丢失的数据包,

  • 如果在收到重复的ACK,cwnd加一个MSS
  • 如果收到新的,则将cwnd设置为阈值,进入拥塞避免状态
  • 拥塞发生

一般两种情况会造成拥塞(超时和三次重复ACK)

  1. 超时重传导致的,那么慢启动阈值会设置成cwnd的一半,然后将cwnd设置为1之后开始慢启动,然后到达阈值后会进行拥塞避免;这种感觉就是突然的卡顿
  2. 快速重传导致的:这时会执行快速恢复

2.TCP 吞吐量及公平性

2.1 吞吐量

在这里插入图片描述

2.2 公平性
  • 概述

如果 K个TCP会话分享一个链路带宽为R的瓶颈,每一个会话的有效带宽为 R/K

  • 公平阐述
    在这里插入图片描述

  • UDP

当TCP和UDP竞争时,由于UDP的特性会导致没有任何公平性可言

八、传输层总结

1.TCP如何实现可靠传输

  • 前言

TCP的可靠传输基础是RDT(停止等待)协议,而为了弥补缺点又引入流水线协议(即滑动窗口)

  • 流水线协议是基于滑动窗口才能实现的,发送和接收双方维护一个接收窗口和一个发送窗口,因为时全双工
  1. 发送方窗口的构成为四部分:窗口外发送已确认、窗口内发送未确认、窗口内未发送未确认、窗口外未发送未确认
  2. 接收方窗口的构成:窗口外接收已确认,窗口内可以接收的字节,窗口外不可接收的字节
  • 概述

从以下八个方面来实现:

  1. 应用数据被分割为最适合传输的报文段
  2. TCP会对每个报文段进行标号,接收方也按序接收并交给应用层
  3. 校验和:检测数据传输过程中的任何变化,如果校验和不通过,TCP将丢弃和不确认收到
  4. 接收端会收到重复数据
  5. 流量控制
  6. 拥塞控制
  7. ARQ协议:这个其实就是RDT和流水线协议的统称;前者对应停止等待 ARQ 协议,后者对应连续 ARQ 协议。
  8. 超时重传:设置计时器,对于超时重传的时间是根据RTT的变化以及RTT的变化偏差(RTT时间波动的值、方差。有时也叫抖动)而动态变化的

2.TCP和UDP的区别

  1. 连接方面
  • TCP 是面向连接的传输层协议,传输数据前先要建立连接。
  • UDP 是不需要连接的,封装成UDP报文会立刻传递给网络层。
  1. 数据可靠性方面
  • TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达。
  • UDP 是尽最⼤努力交付,不保证可靠交付数据。
  1. 提供服务的对象
  • TCP 是⼀对⼀的两点服务,即⼀条连接对于了两个进程的通信。
  • UDP ⽀持⼀对⼀、⼀对多、多对多的交互通信。
  1. 流量控制,拥塞控制
  • TCP 有拥塞控制和流ᰁ控制机制,保证数据传输的安全性。
  • UDP 则没有,只管消息的传递。
  1. 首部开销
  • TCP 首部长度长,首部在没有使用选项字段时是 20 个字节,如果使用了选项字段则会变⻓的。
  • UDP 首部只有 8 个字节,并且是固定不变的。
  1. 传输方式
  • TCP 是流式传输,没有边界,但保证顺序和可靠。
  • UDP 是⼀个包⼀个包的发送,是有边界的,但可能会丢包和乱序。
  1. 分片方式不同
  • TCP 的数据大小如果大于 MSS ,则会在传输层进行分片,目标主机收到后,也同样在传输层组装 TCP数据包,如果中途丢失了⼀个分片,只需要传输丢失的这个分片。
  • UDP 的数据大小如果大于 MTU ,则会在 IP 层进行分片,⽬标主机收到后,在 IP 层组装完数据,接着再传给传输层,但是如果中途丢了⼀个分片,在实现可靠传输的 UDP 时则就需要重传所有的数据包。这样显然效率十分低下,所以UDP 发送的数据报应该小于MUT。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值