计算机网络 自顶向下方法 第三章 运输层

Tags:计算机网络

第三章 运输层


3.1 概述和运输层服务

3.1.1 运输层和网络层的关系

  • 网络层提供了 主机 之间的逻辑通信。而运输层为运行在 不同主机上的进程 提供逻辑通信。
  • 运输层协议只工作在端系统上。
  • 运输协议能提供的服务受制于底层网络协议的服务模型。
  • 网络层协议,即 IP 协议,其服务模型是 尽力而为交付服务 ,但不做任何的保证。是 不可靠服务

3.1.2 因特网运输层概述

  • UDP 提供了一种不可靠、无连接的服务。
  • TCP 提供了一种可靠的、面向连接的服务。
  • 进程到进程的数据交付和差错检测是两种最低限度的运输层服务,也是 UDP 能提供的仅有的两种服务。

3.2 多路复用与多路分解

  • 多路分解: 将运输层报文段中的数据交付到正确的套接字。
  • 多路复用: 在源主机从不同的套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文传递到网络层。
  • 运输层多路复用要求:
    • 套接字有唯一标识符。
    • 每个报文段有特殊字符(端口号)来指示该报文段所要交付到的套接字。
    • 端口号:一个 16 比特的数,在 0 ~ 65535 之间。其中 0 ~ 1023 是周知端口号,是受限制的。

3.2.1 无连接的多路复用与多路分解

  • clientSocket = socket(socket.AF_INET, socket.SOCK_DGRAM) 创建一个 UDP 套接字时,系统会自动为该套接字分配一个未被其他 UDP 套接字使用的端口号。
    也可以用clientSocket.bind(('',23333)) 显式的分配一个端口号。
  • 通常,应用程序的客户端让运输层自动地分配端口号,而服务器则分配一个特定的端口号。
  • 一个 UDP 套接字是由一个包含 目的 IP 地址目的端口号二元组 标识的。

3.2.2 面向连接的多路复用与多路分解

  • TCP 套接字是由一个 四元组(源 IP 地址,源端口号,目的 IP 地址,目的端口号)来标识的。

3.3 无连接运输:UDP

  • 选择 UDP 的原因:
    • 关于何时、发送什么数据的应用层控制更为精细。
    • 无需连接建立。
    • 无连接状态。
    • 分组首部开销小。
  • 用 UDP 建立可靠数据传输机制可以在应用层中实现。

3.3.1 UDP 报文结构

UDP 报文段结构
- 首部只有 4 个字段,每个字段 2 字节。其中,length 指示了 UDP 报文段中的 首部加数据的字节数

3.3.2 UDP 检验和(上图中的 checksum)

  • 检验和 是 UDP 的差错检测机制。其实现方法是:
    1. 将 UDP 报文按 16 比特进行分组。
    2. 将两个 16 比特的数字相加得到一个 32 位的数。
    3. 将 2 中得到的 32 比特数的 高 16 位和低 16 相加。
    4. 重复第 2 步直到得到的和的高 16 位为 0。
    5. 将得到的 16 比特的数按位取反即为 检验和。
      • 注:计算之前的检验和为 0
      • 如果传输没有出错,则在接收方处计算的的检验和将是 11111111111111。若不是,则数据有错。

3.4 可靠数据传输原理

3.4.1 构造可靠数据传输协议

在这节将一步步研究一系列协议,它们一个比一个复杂,最后得到一个无错、完全可靠的数据传输协议。

1. 经完全可靠信道的可靠传输协议: rdt 1.0

  • 这是最简单的情况,假设底层信道是完全可靠的。
  • 有限状态机(FSM):
    • 箭头指示了协议从一个状态变迁到另一个状态。
    • 引起变迁的事件显示在横线的上方。
    • 事件发生时所采取的动作显示在横线的下方。
    • ^ 表示什么都不做。
      下图是发送方和接收方的 有限状态机
      rdt 1.0
  • 发送方:
    • rdt_send(data): 接收较高层的数据。
    • make_pkt(data): 将数据打包成分组。
    • udt_send(packet): 将分组发送到信道中。
  • 接收方:
    • rdt_rcv(data): 从底层信道接收一个分组。
    • extract(packet,data): 从分组中取出数据。
    • deliver_data(data): 将数据传送给较高层。

2. 经具有比特差错信道的可靠数据传输:rdt 2.0

  • 假设底层信道传输的数据可能会有比特差错。但是仍然不会丢包。
  • 在接收方的协议中加入:
    • 差错检测
    • 接收方反馈
      • 肯定确认(ACK)
      • 否定确认(NAK)
    • 重传
      接收到有差错的分组时,发送方重传该分组。
  • 下图是 rdt 2.0 的 FSM:
    rdt 2.0
    • 当发送方处于等待 ACK 或 NAK 的状态时,它不能从上层获得数据。这被称为 停等协议

2.1 rdt 2.1

  • rdt 2.0 中有一个致命的缺陷,就是没有考虑到 ACK 和 NAK 分组受损的可能性。
  • 解决这个新问题的一个简单的方法就是在数据分组中添加一个字段,让发送方对其数据分组编号,即将发送数据分组的 序号 放在该字段。
  • 于是,接收方只需要检查序号即可确定收到的分组是否一次重传。
  • 对于停等协议这种简单的情况,1 比特的序号就足够了。
  • 下图是 rdt 2.1 的 FSM:
    rdt 2.1 sender
    rdt 2.1 receiver

2.2 rdt 2.2

  • 当收到受损的分组时,rdt 2.0 的接收方会发送一个否定确认 NAK。
  • 如果不发送NAK,而是对上次正确接收的分组发送一个 ACK,则也能实现和 NAK 一样的效果。
  • 下图是 rdt 2.2 的 FSM:
    rdt 2.2 sender
    rdt 2.2 receiver

3. 经具有比特差错的丢包信道的可靠数据传输:rdt 3.0

  • 现在假定除了比特受损外,底层信道还会丢包。
  • 在 rdt 3.0 中,丢包的问题让发送方解决。不管是发送的分组丢失,还是接收方返回的确认分组丢失,只要在经过一定的时延后,让发送方重发该分组即可。由此产生的 冗余数据分组 则由接收方通过序号处理。
  • 下图是 rdt 3.0 发送方的 FSM:
    rdt 3.0 sender
  • 因为分组序号在 0 和 1 之间交替,因此 rdt 3.0 有时被称为 比特交替协议
    比特交替协议

3.4.2 流水线可靠数据传输

  • rdt 3.0 是一个功能正确的协议,但是由于它是一个停等协议,大部分的时间都浪费在等待确认上面,所以性能不好。
  • 解决这种特殊性能问题的一个简单的方法是:不使用停等方式运行,允许发送方发送多个分组而无需等待确认。这种技术被称为 流水线
  • 要使用流水线技术,则须:
    • 增加序号范围。因为要传送多个分组,而每个传输中的分组必须有一个单独的序号。
    • 协议的发送方和接收方两端必须能缓存多个分组。发送方至少得能缓存那些已发送但未确认的分组,而接收方或许也需要缓存那些已经正确接收的分组。
    • 所需序号的范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。
    • 流水线的差错恢复有两种基本方法:
      • 回退 N 步
      • 选择重传

3.4.3 回退 N 步(GBN)

  • 回退 N 步协议 中,允许发送方发送多个分组而不需等待确认,但它也受限于在流水线中未确认的分组数不能超过某个最大允许数 N。
    在 GBN 中发送方看到的序号
  • 基序号(base)为最早的未确认分组的序号。
  • 下一个序号(nextseqnum)为下一个待发分组的的序号。
  • N 常被称为 窗口长度,GBN 协议也常被称为 滑动窗口协议
  • 在实践中,一个分组的序号承载在分组首部的一个固定长度的的字段中。
  • 如果该字段的比特数是 k ,则该序号范围是 [0,2k1] ,是一个长度为 2k 的环。
  • 下图是 GBN 发送方的扩展 FSM 描述:
    GBN 发送方的扩展 FSM 描述
    • GBN 的发送方必须响应三种类型的事件:
      • 上层的调用:若窗口未满,则产生一个分组将其发送。
      • 收到一个 ACK:对序号为 n 的分组的确认采取 累积确认,表明接收方已正确接收到包括 n 的序号在内的 n 的以前的所有分组。
      • 超时事件:只使用一个定时器,即最早的已发送但未被确认的分组所使用的定时器。如果出现超时,则发送方重传所有已发送但还未被确认的分组。如果收到一个 ACK,但仍有已发送但未被确认的分组,则重启定时器。如果没有已发送但未确认的分组,该定时器被终止。
  • 下图是GBN 接收方的扩展 FSM 描述:
    GBN 接收方的扩展 FSM 描述
    • 如果一个序号为 n 的分组被正确收到,并且按序(上次交付给上层的数据的序号是 n-1),则接收方为分组 n 发送一个 ACK,并将该分组中的数据交付到上层。在其他所有情况下,接收方丢弃该分组。并为最近按序接收的分组重新发送 ACK。

3.4.4 选择重传(SR)

  • GBN 也存在一些性能问题,单个分组的错误会引起大量分组的重传。
  • 选择重传 通过让发送方仅重传那些它怀疑在接收方出错的分组而避免了不必要的重传。
  • 下图是选择重传发送方和接收方的序号空间:
    选择重传发送方和接收方的序号空间
  • SR 发送方的事件和动作:
    • 从上层接收数据: 检查下一个可用于该分组的序号,若在发送方的窗口内,则将数据打包发送。
    • 超时: 定时器再次用来防止丢失分组。但是现在每个分组必须得有单独的定时器。
    • 收到 ACK:倘若该分组序号在窗口内,则 SR 发送方将那个被确认的分组标记为已接收。如果该分组的序号等于send_base,则窗口基序号向前移动到具有最小序号的未确认分组处。如果窗口移动了并且该序号落在窗口内的未发送分组,则发送这些分组。
  • SR 接收方将确认一个正确接收的分组而不管其是否按序。
  • SR 接收方的事件于动作:

    • 序号在 [rcv_base, rcv_base + N -1] 内的分组被正确接收:在此情况下,收到的分组落在接收方的窗口内,一个选择 ACK 被回送给发送方。如果该分组以前没收到过,则缓存该分组。如果该分组的序号等于接收窗口的基序号,则该分组及以前缓存的序号连续的分组交付给上层。
    • 序号在 [rcv_base - N, rcv_base - 1] 内的分组被正确接收: 产生一个 ACK,即使该分组是接收方以前已确认过的分组。
    • 其他情况:忽略该分组。
  • 窗口长度必须小于或等于序号空间大小的一半。


3.5 面向连接的运输:TCP

3.5.1 TCP 连接

  • 由于 TCP 协议只在端系统中运行,而不在中间的网络元素(路由器和链路层交换机)中运行,所以中间的网络元素不会维持 TCP 连接状态,不会为该连接分配任何缓存和变量。其连接状态完全保留在两个端系统中。
  • TCP 连接提供的是 全双工服务
  • TCP 建立连接需要 三次握手,其中,前两次握手不承载”有效荷载“,第三次握手可以承载有效荷载。
  • 通过套接字发送数据过程如下图:
    TCP 发送缓存和接收缓存
  • TCP 将数据引导到该连接的 发送缓存 里,接下来 TCP 就会不时地从发送缓存里取出一块数据。
  • TCP 可从缓存中取出并放入报文段的数据数量受限于 最大报文段长度(MSS)。该长度是指报文段里应用层数据的最大长度,而不是包括 TCP 首部的 TCP 报文段的最大长度。

3.5.2 TCP 报文结构

TCP 报文段结构

  • 16 比特的 源端口号 和 16 比特的目的 端口号。用于多路分解和多路复用。
  • 32 比特的 序号(sequence number)字段。一个报文段的序号 是该报文段数据字段首字节的序号。
  • 32 比特的 确认号(Acknowledgement number)字段。主机 A 填充进报文段的确认号是主机 A 期望从主机 B 收到的下一字节的序号
  • 16 比特的 接收窗口(Receive window)字段。用于指示接收方愿意接收的字节数量。
  • 4 比特的 首部长度(header length)字段。指示了以 32 比特的字为单位的 TCP 首部长度。
  • 可变与变长的 选项(options)字段。用于发送方与接收方协商最大报文段长度时,或在高速网络环境下作用窗口调节因子时使用。
  • 6 比特的 标志(flag)字段
    • ACK 是对成功接收一个报文段的确认。
    • RST、SYN 和 FIN 用于连接的建立和拆除。
    • PSH 被设置时,指示接收方应立即将数据交给上层。
    • URG 比特用来指示报文段里存在着被发送端上层实体置为“紧急”的数据。紧急的最后一个字节由 16 比特的 紧急数据指针(Urgent data pointer)字段 指出。
    • 注:在实践中,PSH 、URG 和 紧急数据指针 并不 使用。

3.5.3 往返时间的估计与超时

  1. 估计往返时间

    • 报文段的样本RTT:SampleRTT
    • SampleRTT 均值:EstimatedRTT
      EstimatedRTT=0.875EstimeatedRTT+0.125SampleRTT
  2. 设置和管理超时重传时间

    TimeoutInterval=EstimatedRTT+4DevRTT

3.5.4 可靠数据传输

  • 在 rdt 3.0 中,假定每一个已发送但未确认的报文段都与一个定时器相关联。这在理论上是最简单的,但是维护定时器需要相当大的开销。所以一般只使用 单一 的重传定时器。
  • 下图是简化的 TCP 发送方:
    简化的 TCP 发送方
  • TCP 发送方有三个与发送和重传有关的事件:

    • 从上层应用程序接收数据
    • 定时器
    • 收到 ACK
  • 超时间隔加倍
    当超时事件发生时,每次 TCP 重传时都会讲下一次的超时时间间隔设为先前值的两倍,直到其他两个事件发生时,TimeoutInterval 的时间才会由最近的 EstimatedRTT 和 DevRTT 推算得到。

  • 快速重传

    • 超时重传存在的问题是超时的周期较长,会增加端到端时延。
    • 但是,发送方可以在超时事件发生之前通过 冗余 ACK 来较好的检测丢包情况。
    • 下表是 TCP 接收方的 ACK 接收策略:
事件 TCP 接收方动作
具有所期望的序号的按序报文到达。所有在期望序号以及之前的数据都已被确认 延迟的 ACK。对另一个按序报文段的到达最多等待 500ms。如果下一个按序报文段在这个时间间隔内没有到达,则发送一个 ACK
具有所期望的序号的按序报文到达。另一个按序报文段等待 ACK 传输 立即发送单个累积 ACK,以确认两个按序报文段
比期望序号大的时序报文到达。检测出间隔 立即发送冗余 ACK,指示下一个期待字节的序号(其为间隔的低端的序号)
能部分或完全填充接收数据间隔的报文段到达 倘若该报文段起始于间隔的低端,则立即发送 ACK

猜你喜欢

转载自blog.csdn.net/memoryd/article/details/74995521