计算机网络-传输层

时间:2021-11-24 14:36:29


用户数据报协议UDP

  • UDP数据报的特点 
    1. 面向数据报
    2. 不提供可靠性——并不能保证能否到达目的地
    3. 应用程序必须关心IP数据报的长度——因为有可能要分片
  • UDP封装 
    计算机网络-传输层
  • UDP首部 
    计算机网络-传输层
    • 源端口号字段:发送进程
    • 目的端口号字段:接收进程
    • UDP长度字段UDP首部和UDP数据的字节长度,最小值为8字节(也就是说数据段可以为空)
    • UDP校验和字段:覆盖UDP首部和UDP数据
  • TCP端口号和UDP端口号是相互独立的——即TCP端口号由TCP检查,而UDP端口号由UDP检查

UDP校验和

  • 概念:由发送端计算,然后由接收端验证,其目的是为了发现UDP首部和数据在发送端到接收端之间发送的任何改动
  • TCP的校验和是必需的,但UDP的校验和是可选的
  • UDP数据报的长度在检验和计算过程中出现了两次
  • 填充:为了计算校验和——因为UDP数据报长度可以为奇数,但校验和的算法以16-bits为单位(即校验长度必须为偶数),所以可能要在尾部填充0

传输控制协议TCP

协议概念

  • TCP提供一种可靠的面向连接的字节流服务

    • 面向连接 
      1. 客户端和服务器彼此交换数据之前必须先建立一个TCP连接——类似于打电话(先拨号,接通之后再对话)
      2. 在一个TCP连接中,仅有两方进行通信——这意味着多播和广播不能用于TCP
    • 可靠 
      1. 应用数据被分割成合适长度的数据块(报文段或段)发送——UDP数据长度可变
      2. 超时重传——发送之后启动定时器,若不能及时到达受到确认信息,则重新发送该TCP报文
      3. 接收端收到报文后会发送一个确认信息
      4. 校验和——对首部和数据都进行校验,若数据在传输过程中发送任何变化,都会引起校验和的差错,TCP检查出错误后会丢弃这些报文段,并希望发送端进行超时重发
      5. TCP会对收到的数据重新排序——因为IP不能保证数据顺序到达
      6. TCP丢弃重复的数据——因为IP数据报会重复到达
      7. 流量控制——TCP连接的每一方都有固定大小的缓冲空间,接收端只允许另一端发送接收缓冲区所能接纳的数据
    • 全双工:表示数据能在两个方向上独立的传输——因此连接的每一方必须保持每个方向上的传输数据序号
  • TCP封装 
    计算机网络-传输层

  • TCP首部 
    计算机网络-传输层

    • 源端口号字段:源端的端口号——用于寻找发送端的应用程序
    • 目的端口号字段:目的端的端口号——用于寻找接收端的应用程序
    • 序号字段:用于标识该报文段中的字节流的起始位置——即数据序号(可以进行重新排序),还包括初始序号(建立连接时使用,且只有SYN标志为1时,初始序号才有效)
    • 确认序号字段:表示期望收到的下一个字节的序号——即上一个收到的字节的序号加1(只有ACK标志为1时,确认序号才有效)
    • 首部长度字段:首部的长度(以4字节为单位)——需要该字段是因为任选字段的长度是可变的,由于该字段共4位,因此有 20TCP60 20字节⩽TCP首部长度⩽60字节
    • 保留位字段:后两位CWRECE用于实现显示拥塞控制ECN机制

      • CWR(拥塞窗口减少标志位):由发送端设置,若为1,则表示发送方接收到了接收端发出的设置了ECE标志的TCP包,并且通知接收方:发送发已按拥塞控制机制进行了回应(可能减少拥塞窗口)
      • ECE(ECN及拥塞通知标志位):由接收端设置若为1,则表示在TCP三次握手时一个TCP端是具备ECN功能的,并且表明接收到的TCP包的IP头部的ECN被设置为11(即接收端发现了拥塞) —— 用以通知发送方网络上发生了拥塞(若ECE置为1)。

        • 显示拥塞通知ECN:路由器在出现拥塞时通知TCP。当TCP段传递时,路由器使用IP首部中的2位来记录拥塞,当TCP段到达后,接收方知道报文段是否在某个位置经历过拥塞。然而,需要了解拥塞发生情况的是发送方,而非接收方。因此,接收方使用下一个ACK通知发送方有拥塞发生(ECE置为1),然后,发送方做出响应(CWR置为1),缩小自己的拥塞窗口。
    • 标志位(有效位)字段:用于判断TCP首部中的对应字段是否有效

      • URG:若为1,则表示紧急指针字段有效
      • ACK:若为1,则表示确认序号字段有效
      • PSH:若为1,则表示接收方应尽快将这个报文段交给应用层
      • RST:若为1,则表示重新连接
      • SYN:同步序号,用于发起一个连接——若为1,则表示正在建立连接
      • FIN:若为1,则表示发送端完成发送任务
    • 窗口大小字段:用于流量控制(表示接收方还能下一次还能接收多少数据,若为0,则发送方会停止发送数据,知道窗口大小字段大于0为止),初始值确认序号字段指明的值(表示接收端正期望接收的字节),由于该字段占16位,因此窗口大小最大为 2161=65535 216−1=65535字节,且该字段的值可变
    • 校验和字段:对整个TCP报文(TCP首部和TCP数据)进行校验
    • 紧急指针字段:一个正的偏移量,和序号字段中的值相加表示数据最后一个字节的序号
    • 任选字段字段:通常是最长报文大小MSS
    • 数据字段
  • 四元组—— (IP,,IP,) (源IP地址,源端口号,目的IP地址,目的端口号)用于识别唯一的一个TCP连接

  • 最大报文长度MSS默认的TCP最大分段大小是536TCP报文的数据区最大长度)——当一个主机想要把MSS设置为一个非默认的值时,MSS大小会以一个TCP可选项的方式在握手时的SYN包中定义。由于最大分段大小被一个TCP参数控制,主机可以在接下来的任意分段中改变它,且每个数据流的方向都可以使用不同的MSS
  • MTUMSS的区别 
    • MTUIP数据报的最大长度——包括IP首部、TCP首部、TCP数据区最大长度(MSS),超过MTUIP数据包会被分片
    • MSSTCP数据区最大长度,数据区部分超过MSS大小的TCP报文会被丢弃
    • MTU=IP+TCP+MSS MTU=IP首部+TCP首部+MSS
  • 超时重传TCP通告在发送时设置一个定时器来解决这种问题,如果当定时器溢出时还没有收到确认,它就重传数据
  • 往返时间RTT =+ 往返时间=发送延迟时间+确认延迟时间

TCP连接的建立和终止

TCP建立连接(三次握手)

  • 图示 
    计算机网络-传输层
  • 步骤

    1. 客户端发送一个同步报文,该报文标志字段中的SYN位置为1设置客户端的初始序列号为seq=x,并指明客户端打算连接的服务器端口
    2. 服务器返回一个确认报文,该报文标志字段中的SYN位和ACK位都置为1,并设置确认序列号为(设置为ack=x+1——客户端的初始序列号加1,以对客户端的SYN报文段进行确认),服务器的初始序列号为seq=y
    3. 客户端返回一个确认报文,该报文标志字段的SYN位置为1,且确认序列号置为ack=y+1(设置为ack=y+1——服务器的初始序列号加1,以对服务器的SYN报文段进行确认),同时设置客户端的初始序列号为seq=x+1
  • 报文布局

    1. SYN位为1、序号字段为x(发送端   接收端)
    2. SYN位和ACK位都为1、序号字段为y、确认字段为x+1(发送端   接收端)
    3. ACK位为1、序号字段为x+1、确认字段为y+1(发送端   接收端)

    注:传输过程中还包括了通信双方的MSS以进行协商


  • 为什么TCP连接需要三次握手,两次不可以吗?为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。 

    已失效的连接请求报文段产生在这样一种情况下client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

TCP连接终止序列(四次握手)

  • 图示 
    计算机网络-传输层
  • 步骤:首先执行关闭操作的是主动关闭方(可能为客户端,也可能为服务器)

    1. 某一端首先执行主动关闭(调用close)——发送一个FIN分节(表示数据发送完毕)——此时主动关闭方处于FIN_WAIT_1状态(等待服务器端的ACKFIN
    2. 另一端的TCP端口接收到FIN分节后,返回一个确认信号ACK(对接收到的FIN进行确认,并将其作为文件结束符放入接收队列中)——此时主动关闭方处于FIN_WAIT_2状态(等待服务器端的FIN),被动关闭方处于CLOSE_WAIT状态(等待应用程序发送FIN
    3. 一段时间后,从接受队列中获得文件结束符的应用程序发送一个自己的FIN分节(表示数据接收完毕),并执行被动关闭(调用close))——此时主动关闭方处于TIME_WAIT状态(等待两个MSL的时间 —— 为了处理超时重传),被动关闭方处于LAST_ACK状态(等待客户端的最后一个ACK
    4. 主动关闭方发送一个确认信号ACK(对接收到的FIN进行确认)——之后主动关闭方和被动关闭方都处于CLOSED状态
  • 报文布局

    1. FIN位和ACK位都为1、序号字段为x、确认字段为y(主动关闭端   被动关闭端)
    2. ACK位为1、确认字段为x(主动关闭端   被动关闭端)
    3. FIN位为1、序号字段为y(主动关闭端   被动关闭端)
    4. ACK位为1、确认字段为y+1(主动关闭端   被动关闭端)
    1. 半关闭状态(FIN_WAIT_1FIN_WAIT_2TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力,接口通过这种方式说明:

      我已经完成了数据传送,因此发送一个FIN给另一端,但我还想接收另一端发来的数据,直到他给我发来一个FIN,之后我将进入TIME_WAIT状态

    2. 主动关闭的一方不直接进入CLOSED状态,而是进入TIME_WAIT状态,并且停留两倍的MSL时长的原因:这是因为TCP是建立在不可靠网络上的可靠的协议。

      例子:主动关闭的一方收到被动关闭的一方发出的FIN包后,回应ACK包,同时进入TIME_WAIT状态,但是因为网络原因,主动关闭的一方发送的这个ACK包很可能延迟,从而触发被动连接一方重传FIN包。极端情况下,这一去一回,就是两倍的MSL时长。如果主动关闭的一方跳过TIME_WAIT直接进入CLOSED,或者在TIME_WAIT停留的时长不足两倍的MSL,那么当被动关闭的一方早先发出的延迟包到达后,就可能出现类似下面的问题:

      1. 旧的TCP连接已经不存在了,系统此时只能返回RST
      2. 新的TCP连接被建立起来了,延迟包可能干扰新的连接

      不管是哪种情况都会让TCP不再可靠,所以TIME_WAIT状态有存在的必要性。

    3. 第二步和第三步不是同步发生的,处于这两步之间的主动关闭方仍在接收数据

TCP数据交互

Nagle算法

  • 目的尽可能发送大块数据,避免网络中充斥着许多小数据块 —— 为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。
  • 定义Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。 所谓小段,指的是小于MSS尺寸的数据块,所谓未被确认,是指一个数据块发送出去后,没有收到对方发送的ACK确认。
  • 规则: 
    1. 若包长度达到MSS,则允许发送
    2. 若该包含有FIN,则允许发送
    3. 若设置了TCP_NODELAY选项,则允许发送
    4. 若未设置TCP_CORK选项,但所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送
    5. 若上述条件都未满足,但发生了超时(一般为200ms),则立即发送

流量控制

  1. TCP协议的滑动窗口具体是怎样控制流量的?
  2. TCP的流量控制和拥塞控制

基本原理

  • 流量控制的定义TCP利用滑动窗口协议来完成流量控制 —— 即接收方通过告知发送方自己的滑动窗口大小,从而控制发送方的发送速度,以防止发送方发送速度过快。

    接收方通过ACK数据报告知发送方自己还能接收多少字节的数据,其基本原理如下:

    • ACK数据报中通常包含两方面的信息: 
      1. 确认序列号 n n表示接收方期望接收到的下一字节的序号为 n n —— 该 n n代表接收方已经接收到了前 n1 n−1字节数据,此时如果接收方收到第 n+1 n+1字节数据而不是第 n n字节数据,则接收方会继续发送确认序列号为 n n的ACK的。
      2. 接收方当前窗口大小 m m表示接收方从序列号 n n开始,还能接收 m m个字节的数据
    • 假设当前发送方已发送到第 x x字节(其中 xn x⩾n),则发送方还可以发送的字节数为 y=m(xn) y=m−(x−n),这就是滑动窗口控制流量的基本原理。

    如下图所示,其中确认序列号为 n=36 n=36,发送端当前已将第 x=51 x=51个序列号发送出去,而当前接收方的滑动窗口大小为 m=5536 m=55−36,因此发送方还能将序号为 [52,55] [52,55]的数据发送出去。 
    计算机网络-传输层

快发送和慢接收

计算机网络-传输层

  1. 发送方连续发送4个背靠背的数据报文段去填充接收方的窗口,然后停下来等待一个ACK
  2. 接收方先发送一个ACK,但通告其窗口大小为0,说明接收方已收到所有数据,但这些数据都在接收方的缓冲区中——因为应用程序还没有来得及读取这些数据,此时发送方不能再发送数据。
  3. 接收方再发送一个ACK(窗口更新),表明接收方现在可以接收另外的4096字节的数据,此时发送方可以继续发送数据。

滑动窗口

计算机网络-传输层

  • 如上图所示:当前窗口覆盖了从第4字节到第9字节的区域,表明接收方已经确认了包括第3字节在内的数据,且通告窗口大小为6
  • 当接收方确认数据后,这个窗口不时地向右移动
  • 当左边沿到达右边沿时,发送方将不能继续发送数据
  • 窗口两个边沿的相对运动增加或减少了窗口的大小 
    • 窗口合拢:左边沿向右边沿靠近,这种现象发生在数据被发送但未被确认时——表示还可以发送的数据减少了
    • 窗口收缩:右边沿向左边沿靠近
    • 窗口张开:右边沿向右移动,这种现象发生在接收端已经确认数据并释放TCP接收缓存时,表示允许发送方发送更多的数据

拥塞控制

拥塞控制的原理和算法

慢启动和拥塞避免(已淘汰)

  • 执行慢启动的条件如果发送方设置的超时计时器时限已到但还没有收到确认,那么很可能是网络出现了拥塞,致使报文段在网络中的某处被丢弃。这时,TCP马上把拥塞窗口 cwnd cwnd减小到1,并执行慢开始算法,同时把慢开始门限值 ssthresh ssthresh减半。

  • 慢启动和拥塞避免算法:对每个连接都维护两个变量——拥塞窗口大小(cwind)和慢启动门限(ssthresh),当 cwind<ssthresh cwind<ssthresh时,使用上述慢启动算法;当 cwind>ssthresh cwind>ssthresh时,停止使用慢启动算法,改用拥塞避免算法 
    计算机网络-传输层

    • 慢启动:让拥塞窗口cwind较快地增大,每经过一个往返时间RTT就把发送方的拥塞窗口cwind加倍
    • 拥塞避免:让拥塞窗口cwind缓慢地增大——每经过一个往返时间RTT就把发送方的拥塞窗口cwind1
    • 规则无论慢启动开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢启动门限ssthresh设置为当前出现拥塞时的发送方窗口值的一半(但不能小于2),然后重新执行慢启动算法(即把拥塞窗口cwind重新设置为1,并执行慢启动算法)

快重传和快恢复

  • 快重传和快恢复的基本原理:一条TCP连接有时会因等待重传计时器的超时而空闲较长的时间,慢开始和拥塞避免无法很好的解决这类问题,因此提出了快重传和快恢复的拥塞控制方法。在快重传和快恢复算法中,发送端要求接收方每收到一个失序的报文段后就立即发出重复确认 —— 目的是使发送方及早知道有报文段没有到达对方,这样发送端就可以通过接收端发来的重复确认信息代替自己的超时重传机制来判断是否有网络拥塞发生。 
    计算机网络-传输层
    1. 当发送方连续收到三个重复确认(确认序列号相同,表示报文失序,而该序列号对应的报文未能及时到达)时,执行“乘法减小”算法,慢启动门限减半 
      计算机网络-传输层
    2. 由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢启动算法,而是执行快恢复算法——即cwind值设置为慢启动门限减半后的值,然后开始执行拥塞避免算法,拥塞窗口cwind值线性增大。避免了当网络拥塞不够严重时采用”慢启动”算法而造成过大地减小发送窗口尺寸的现象。

总结

流量控制和拥塞控制的区别

  • 流量控制: 所谓流量控制就是让发送方的发送速率不要太快,使接收方来得及接收 —— 如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失,利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。
  • 拥塞控制:所谓拥塞控制就是防止过多的数据注入到网络中,使网络中的路由器或链路不致过载。