计算机网络之传输层

传输层

传输层的概述

​ 传输层位于应用层和网络层之间,为运行在不同主机的应用进程提供了逻辑通信。从应用程序的角度看,通过逻辑通信,运行不同进程的主机好像直接相连一样。

​ 传输层协议是在端系统实现而非路由器中实现,在发送端,传输层将应用层传输来的报文分割成分组,每个分组添加上传输层协议的首部,这些分组被称为报文段,之后,传输层把报文段传递给网络层处理,网络层处理之后再发送出去。

因特网传输层协议

  • UDP:UDP为应用程序提供了一种不可靠,无连接的服务,UDP无法保证数据完好无缺地交付给接收方。
  • TCP:TCP为应用程序提供了一种可靠,面向连接的服务。TCP相对于UDP多了可靠数据传输服务、拥塞控制、流量控制等功能。

无连接传输:UDP

  • UDP基于IP协议的基础上,增加了复用/分用、简单的错误校验的功能。

  • UDP可能发生丢失或乱序问题。

  • UDP发送方和接收方不需要握手,没有UDP段的处理独立于其他段。

UDP的优势

  • 无需建立连接
  • 实现简单
  • 头部开销少
  • 没有拥塞控制机制,应用层可以更好控制流量和传输速率

UDP校验和

​ 目的:检测报文段是否传输过程中发生反转。

  • 校验和的创建:发送方将报文段的内容视为16-bit整数,将所有整数相加(如果有进位,则将进位数字加到最后)之后按位取反。
  • 校验和的校验:计算收到的报文段的校验和,如果和原校验和进行比对。如果不相等,则出现错误;如果相等,代表没有检测出错误(不代表没有发生错误)。

可靠数据传输原理

rdt1.0

​ 底层信道完全可靠,不发生错误,不发生丢包。

过程

  • 发送方:发送方传输层等待上层调用、上层调用之后发送分组。
  • 接收方:接收方传输层等待下层调用、下层调用之后接受分组交付给上层。

rdt2.0

​ 底层信道可能发生错误,但不会发生分组丢失。

过程

  • 发送方

    1. 发送方传输层等待上层调用、上层调用之后发送分组。
    2. 等待接收方发送的ACK或者NAK。
    3. 当接收到ACK后,发送下一个分组;接收到NAK之后,重新发送该分组。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 接收到分组后,使用校验和来检测是否发生错误。
    3. 如果发生错误,向发送方发送NAK;如果没有发生错误,向发送方发送ACK,同时将分组交付给上层。

rdt2.1

​ 如果ACK/NAK发生错误,则发送方重传该分组,但会出现重复分组的问题,为了解决重复分组的问题,使用rdt2.1.

过程

  • 发送方

    1. 发送方传输层等待上层调用、上层调用之后发送分组,附带序列号0或1
    2. 等待接收方发送的ACK或者NAK。
    3. 当接收到ACK后,发送下一个分组,如果上一次发送的序列号为1则此次发送0,如果上一次是0则此次发送1;接收到NAK或ACK/NAK发生错误之后,重新发送该分组,序列号和上一次一样。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 接收到分组后,使用校验和来检测是否发生错误。
    3. 如果发生错误,向发送方发送NAK;如果没有发生错误且收到的分组与预期的分组序列号一致,向发送方发送ACK,同时将分组交付给上层;如果收到的分组与预期的分组序列号不一致,向发送方发送ACK。
  • 注:

    1. 什么是预期的分组序列号?

      如果上一次接收方将分组序列号为1的分组交付给上层,则0上它此次预期的分组序列号,如果上一次接收方将分组序列号为0的分组交付给上层,则1上它此次预期的分组序列号。

    2. 当收到的分组与预期的分组序列号不一致,为何发送ACK?

      收到的分组与预期的分组序列号不一致说明发送方发送了重复的分组,且该分组已经被交付给上层,接收方发送ACK目的是告知发送方发送一下个新的分组。

rdt2.2

​ 取消掉NAK,在ACK中加入被确认分组的序列号

过程

  • 发送方

    1. 发送方传输层等待上层调用、上层调用之后发送分组,附带序列号0或1。
    2. 等待接收方发送的ACK或者NAK。
    3. 当接收到ACK后,发送下一个分组,如果上一次发送的序列号为1则此次发送0,如果上一次是0则此次发送1;接收到与预期序列号不同的ACK或ACK发生错误之后,重新发送分组,序列号和上一次一样。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 接收到分组后,使用校验和来检测是否发生错误。
    3. 如果发生错误或者收到的分组与预期的分组序列号不一致,向发送方发送和上一次序列号一样的ACK;如果没有发生错误且收到的分组与预期的分组序列号一致,向发送方发送带此次序列号ACK,同时将分组交付给上层。

rdt3.0

​ 信道即会发生错误,也会丢失分组,添加定时器机制

过程

  • 发送方

    1. 发送方传输层等待上层调用、上层调用之后发送分组,附带序列号0或1,启动定时器。
    2. 等待接收方发送的ACK或者NAK。
    3. 如果超时,则重传并重启定时器(此过程可能是分组丢失也可能是ACK丢失)。
    4. 当接收到预期序列号ACK后,停止计时器,发送下一个分组,启动定时器,如果上一次发送的序列号为1则此次发送0,如果上一次是0则此次发送1;接收到重复ACK或ACK/NAK发生错误之后,什么也不做,继续等待预期的ACK。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 接收到分组后,使用校验和来检测是否发生错误。
    3. 如果发生错误或者收到的分组与预期的分组序列号不一致,向发送方发送和上一次序列号一样的ACK;如果没有发生错误且收到的分组与预期的分组序列号一致,向发送方发送带此次序列号ACK,同时将分组交付给上层。

流水线机制和滑动窗口

​ rtd3.0性能较差,所以引入流水线机制。

滑动窗口协议

​ 滑动窗口定义了允许使用的序列号范围,窗口的尺寸为N,代表最多有N个等待确认的消息。

GBN滑动窗口协议

计算机网络之传输层

​ 如图所示,窗口的左端是已经发送并且得到ACK的分组,窗口内黄色的是已发送但未ACK的分组,绿色是能发送的分组,白色是暂时不可发送的分组。

过程
  • 发送方

    1. 发送方传输层等待上层调用
    2. 如果有窗口中有可用的序列号,则发送分组,并将黄色部分向后移动,如果现在发送的是窗口的第一个序列号,则启动计时器。
    3. 如果超时,重发所有黄色的分组。
    4. 如果收到ACK,该ACK附带一个序列号为N,将窗口向右移动,移动到N+1。如果此时没有发出去的分组,则停止计时器,如果已经有发出去的分组,则重启计时器
    5. 如果收到错误ACK,什么也不做。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 如果序号为n的分组正确且有序到达,则发送序列号为n的ACK。
    3. 其余情况下,丢弃该分组,并发送最近收到的有序的分组的序列号的ACK

SR协议

​ 接收方能够缓存乱序分组,所以接收方也有一个滑动窗口。

过程
  • 发送方

    1. 发送方传输层等待上层调用
    2. 如果有窗口中有可用的序列号,则发送分组,并将黄色部分向后移动。对每次发送的分组都开启一个单独的计时器
    3. 如果某个计时器超时,则重发那个分组。
    4. 如果接收到了ACK,将接收到ACK的分组标记一下,如果该分组是窗口内最小的,将窗口向右滑动。
  • 接收方

    1. 接收方传输层等待下层调用、下层调用之后接受分组。
    2. 如果该分组乱序,则缓存该分组,如果该分组有序到达,则交付上层。
    3. 发送ACK

面向连接的传输:TCP

TCP报文段

序号与确认号

序号与确认号是TCP报文段中最重要的部分,TCP将传输的数据看作是字节流,并隐式地为每个字节编号。报文段中的序号便是此次传输的数据段的的首字节的字节流编号。确认号是指接收方累积确认过程中最小没有接受到的序号。

例如,主机A向主机B发送500000字节的数据,TCP将数据分割为500个报文段,每个报文段中含有1000字节的数据,报文段的首序号为0。则第一次发送的报文段的序号为0,第二次为0+1000=1000,第三次为1000+1000=2000。假设第一个报文段到达主机B,主机B就收到了0-1000的数据,这时最小没有收到的数据为1001,则主机B向主机A发送确认号为1001的报文段。如果主机A发送的第二个报文段丢失而第三个报文段到达主机B,则主机B缓存上第三个报文段,继续向主机A发送确认号为1001的报文段。如果主机B收到了再次发送的第二个报文段,则将报文段与缓存中的数据拼接,发出确认号为2001的报文段。

冗余ACK

什么时候会出现冗余ACK

  • 乱序:发送方序号大的数据报先于序号小的数据报到达接收方,接收方根据累积确认原则发送最小没有接收到的序号,这时便会产生冗余ACK。
  • 丢包:序号小的数据报丢失,序号大的数据包没有丢失,这种情况实际上就是乱序。

定时器

何时启动定时器?

  • 当发送报文时没有定时器启动时启动定时器。
  • 当超时重传之后启动定时器。
  • 当收到一个有效确认报文且此时还有未被确认的报文段时启动定时器。

流量控制

连接的两端都会维持一个缓存队列,对发送方发送速率的控制防止其发送的数据超出了接收方的缓存队列的方法叫做流量控制。

接收窗口用rwnd来表示,接收窗口指的是缓存队列可用空间的大小,rwnd时动态变化的。接收方通过将rwnd传递给发送方来告知发送方还有多少的可用缓存空间。发送方要在整个连接的生命周期中确保未被确认的数据大小小于rwnd的大小。

如果接收方发来rwnd为0之后,接收方没有要发送的数据了怎么办?

如果没有任何额外的机制,那么发送方将不会知道何时接收方的缓存空间有空余,那么发送方将进入阻塞状态。实际上,发送方会持续发送1字节数据的报文段,如果接收方有空余,则可以发送rwnd不为0的响应报文段。

连接管理

三次握手

  1. 客户端发送一个报文段首部SYN比特为1的报文段,该报文段的序号是一个随机序号client_isn。
  2. 服务器收到该特殊的报文段后,分配缓存和变量,并向客户端发送一个报文段首部SYN比特为1、确认号为client_isn+1、序号为随机序号server_isn的报文段。
  3. 客户端收到该特殊的报文段后向服务器发送一个报文段首部SYN比特为0、确认号为server_isn+1的报文段。

为何需要三次握手?

  1. 为了防止旧的连接使得整个连接造成混乱。

    假设客户端向服务器发起了SYN报文段,之后由于网络阻塞客户端迟迟未到达服务端,之后客户端再次发送SYN报文段,这时,旧的SYN先到达了服务器,服务器认为客户端想以这个旧的报文段所携带的client_isn为序号,实际上这个是旧的报文段,已经不需要,那么客户端在第三次握手的时候就会告知服务器这个旧的连接终止。

  2. 从上文可以看出,三次握手是要分配必要的空间和变量,通知另一端一些初始信息如序号。

四次挥手

客户端和服务器都可以主动断开连接,假设客户端主动断开连接。

过程

  1. 客户端发送一个特殊的TCP数据报,该数据包的一个标志为FIN设置为1。
  2. 服务器接收到该特殊的数据报,向客户端发送一个确认ACK的数据报。
  3. 服务器发送一个特殊的TCP数据报,该数据包的一个标志为FIN设置为1。
  4. 客户端接收到该特殊的数据报,向服务器发送一个确认ACK的数据报。
  5. 服务器收到确认数据报后关闭连接。
  6. 客户端经过定时等待后关闭连接。

为何需要四次挥手?

客户端发出FIN,说明客户端已经没有了数据想要发送,所以主动断开连接。服务器即使接收到了FIN数据报,回复了ACK,若是服务器仍然在处理数据,并且还想发送,则它就不想关闭连接,如果服务器无数据要处理和发送了,则服务器也发送FIN数据报。

为何需要定时等待?

数据传递过程中,可能有一些应用数据报由于网络延迟迟迟不送达,定时等待时间为两倍的报文最大存活时间,经过定时等待时间之后,可以确保此次链接即使是延迟的数据报也没有了,防止本次连接的数据报传递给下一次新的连接导致数据混乱。

TCP拥塞控制

控制发送速率

​ 通过网络的拥塞程度,动态调节拥塞控制窗口.

感知网络拥塞

  • 超时
  • 三个ACK

加性增-乘性减

​ 逐渐增加发送速率,当发生loss时,快速降低发送速率.

慢启动

​ 当连接开始时,可用带宽可能远远高于初始带宽。所以,当连接开始时,拥塞窗口自1开始指数型增长。

慢启动转加性增

​ 定义一个变量Threshold,当感知到拥塞发生时,Threshold设为发生Loss时拥塞窗口的值的一半。

  • 发生超时:拥塞窗口降为1,慢启动。
  • 3个重复ACK:拥塞窗口将为原来的一半,加性增。
上一篇:Linux进阶TCP三次握手四次挥手


下一篇:字节跳动Java内部学习资料泄露