Skip to content
NotesComputer Networking

自顶向下的计算机网络笔记,覆盖应用层、传输层与网络基础。

第三章:传输层 (Transport Layer)

目录


3.1 传输层服务

传输层的核心任务是:为运行在不同主机上的应用程序实体(进程)提供逻辑通信 (Logical Communication)。借助于逻辑通信,不同主机上的进程就如同直接相连一样。

1. 传输服务与端系统操作

传输协议主要是在端系统 (End Systems) 也就是边缘的主机上运行的,路由器等网络核心设备不处理传输层数据(它们通常只处理到底层网络层)。

  • 发送者 (Sender)
    • 接收应用层传递下来的消息 (App Message)。
    • 确定报文段的首段字段值 (Header values)。
    • 创建并分装成报文段 (Segment),最后把报文段传递给底层的网络层 (IP 层)。
  • 接收者 (Receiver)
    • 从网络层 (IP 层) 接收底层的推上来的报文段。
    • 检查报文段的首部值,并完整提取出应用层消息。
    • 通过对应的套接字 (Socket) 将该消息多路分解定点分发给指定的应用程序进程。

2. 传输层 vs. 网络层:一网打尽区别与联系

要理解传输层,必须搞清它与网络层 (Network Layer) 在服务范围上的根本区别:

  • 网络层:提供主机 (Host) 之间的逻辑通信。
  • 传输层:提供进程 (Process) 之间的逻辑通信。传输层重度依赖于网络层的主基建服务,并在其基础上做了大量增强。

形象的类比:安 (Ann) 与比尔 (Bill) 两家孩子的通信 想象安家的 12 个孩子需要给比尔家的 12 个孩子写信:

  • 主机 (Host) = 房屋 (Houses)
  • 进程 (Process) = 房屋里的孩子们 (Kids)
  • 应用层消息 (App Message) = 信封里的信件文字 (Letters)
  • 网络层协议 = 外面的邮政系统(保证把成堆的信从安家投递到了比尔家门口)。
  • 传输层协议 = 家里的老大安和比尔(拿到邮递员送到家门口的一大捆信后,在家里进一步根据收件人名字,分发到具体对应的弟弟妹妹手里)。

3. 互联网两大主力传输协议

目前,互联网应用程序中提供两种截然不同的传输协议可供选择:

  1. 传输控制协议 (TCP: Transmission Control Protocol)
    • 可靠、有序的传输交付:确保数据无差错、不丢失不乱序。
    • 高级护航特性:提供了包括网络拥塞控制 (Congestion Control)、接收端流量控制 (Flow Control) 以及正式的数据传输前的连接建立 (Connection Setup) 机制。
  2. 用户数据报协议 (UDP: User Datagram Protocol)
    • 不可靠、无序的交付:不保证数据送达和顺序。
    • 本质是对底层 IP “尽力而为 (Best-effort)” 粗犷协议的一种无约束扩展。

⚠️ 传输层的盲区 (不提供的服务): 无论是功能庞大的 TCP,还是精简至极的 UDP,现有的互联网传输层协议都无法提供以下服务:

  • 延迟保证 (Delay guarantees):不能保证数据在某此时限内到达。
  • 带宽保证 (Bandwidth guarantees):不能保证你的应用在网络高峰期能独占多少速率。

3.2 多路复用和多路分解

多路复用(Multiplexing)与多路分解(Demultiplexing)是传输层提供进程间逻辑通信的核心机制。

1. 核心定义

  • 发送端的多路复用(Multiplexing): 传输层从源主机的多个套接字(Socket)收集应用层数据,为每块数据封装上头部信息(主要是端口号)生成报文段,然后将这些报文段传递给网络层。
  • 接收端的多路分解(Demultiplexing): 当传输层从网络层接收到报文段时,根据报文段头部的字段信息(端口号等),将数据定向交付到正确的套接字中。

2. 工作方式与段格式

主机接收到 IP 数据报时:

  • 每个数据报都包含源 IP 地址目的 IP 地址
  • 每个数据报中承载着一个传输层段,段中包含源端口号目的端口号
  • 主机使用 IP 地址端口号共同将报文段定向到适当的套接字。

段格式中的关键字段: 在 TCP/UDP 的报文段首部中,前 32 位被分配给:源端口号(16 bit)目的端口号(16 bit)

3. 无连接多路分解 (UDP)

  • 套接字标识:UDP 套接字仅由一个二元组标识:(目的 IP 地址, 目的端口号)
  • 分发规则
    • 接收主机收到 UDP 段后,检查段中的目的端口号
    • 将该段定向到具有该端口号的套接字。
  • 特征:即使两个 UDP 报文段具有不同的源 IP 地址或源端口号,只要它们的目的 IP 和目的端口号相同,它们就会被定向到同一个接收套接字。

4. 面向连接的多路分解 (TCP)

  • 套接字标识:TCP 套接字由一个四元组唯一标识:
    1. 源 IP 地址
    2. 源端口号
    3. 目的 IP 地址
    4. 目的端口号
  • 分发规则:接收者使用所有这四个值来将报文段定向到对应的套接字。
  • 特征
    • Web 服务器(如 Apache)可以同时支持多个 TCP 套接字。
    • 即使所有进来的 TCP 段都有相同的目的 IP(服务器 IP)和相同的目的端口(如 80 端口),只要它们的源 IP 或源端口不同,它们就会被多路分解到不同的套接字中。

5. 总结

协议多路分解依据备注
UDP目的端口号相同目的地(IP+Port)的报文进同一个 Socket
TCP四元组 (源IP, 源Port, 目的IP, 目的Port)标识唯一的端到端连接
  • 关键点:多路复用和多路分解机制存在于协议栈的所有层中。传输层是利用头部字段来实现进程间的分发。

6. 套接字 (Socket) 与 报文段 (Segment) 的深度关联

理解传输层,本质上是理解数据如何在“虚幻”的套接字与“实体”的报文段之间流转。

  • 基本概念

    • 套接字 (Socket):是应用进程与传输层之间的“门”。在操作系统底层,它是一组数据的描述符。
    • 报文段 (Segment):是传输层的 PDU,由“首部 (Header)” + “应用数据 (Payload)” 组成。其中首部包含的关键信息决定了它应该被塞进哪个“门”。
  • 关系映射:UDP vs. TCP

    • UDP(二元组映射)
      • 内容:UDP 报文段非常简单,仅通过首部的“目的端口”寻找对应的 Socket。
      • 关系:一个 UDP Socket 本质上只绑定了一个本地端口(如 12534)。任何目的地址为此端口的报文段都会无差别地进入这个 Socket。
    • TCP(四元组映射)
      • 内容:TCP 报文段首部包含复杂的连接信息。
      • 关系:一个 TCP Socket 唯一对应一条特定的端到端虚连接。服务器可能在同一个 80 端口上挂载了 1000 个不同的 Socket,系统根据报文段中的(源 IP、源 Port、目的 IP、目的 Port)这四个值的组合,精准地投递到其中一个特定的 Socket 中。

3.3 无连接传输:UDP

UDP(User Datagram Protocol)被称为互联网传输协议的“基础版”或“简化版”。它本质上是在 IP 协议的基础上做了极少的扩展。

1. UDP 的核心特性

  • 尽力而为(Best-effort)服务
    • UDP 报文段可能会在网络中丢失
    • UDP 报文段可能会**无序(Out-of-order)**交付给应用程序。
  • 无连接性(Connectionless)
    • 发送者和接收者之间没有握手过程。
    • 每个 UDP 报文段的处理都是彼此独立的。
  • 为什么需要 UDP?(UDP 的优势)
    • 无需建立连接:减少了建立连接带来的 RTT 往返时延。
    • 简单:发送者和接收者都不需要维护复杂的连接状态。
    • 头部开销小:相比 TCP,UDP 的首部非常短小。
    • 无拥塞控制:UDP 可以根据应用需求尽可能快地发送数据。即使在网络拥塞时,它也会继续尝试发送,这对于某些实时应用非常重要。

2. UDP 的使用场景

  • 多媒体流媒体应用:对数据丢失有一定容忍度,但对传输速率和延迟高度敏感(如视频通话)。
  • DNS(域名系统):查询过程简单,追求极速响应。
  • SNMP(网络管理协议)
  • HTTP/3:为了解决传统 TCP 带来的队头阻塞等问题,QUIC(HTTP/3 的基础)选择建立在 UDP 之上。
  • 可靠性补充:如果需要在 UDP 上实现可靠传输,必须在应用层添加所需的可靠性逻辑和拥塞控制(如 HTTP/3 所做的)。

3. UDP 报文段结构

UDP 首部只有 8 个字节,分为四个字段(每个字段占 16 位/2 字节):

字段长度描述
源端口号16 bit发送进程的端口。
目的端口号16 bit接收进程的目标端口。
长度16 bit包含首部和数据的总字节数。
校验和16 bit用于检测段在传输过程中是否出现了位翻转。

4. UDP 校验和 (Checksum)

目标:检测报文段中的错误(即传输过程中发生翻转的位)。

  • 发送方动作
    1. 将报文段内容(包括数据、首部以及部分 IP 伪首部)看作是一个 16 位整数序列。
    2. 对这些整数进行加法运算(使用反码求和算法:溢出的进位需要加回到结果的最低位,即“回绕”)。
    3. 最后将求和结果取反,存入校验和字段。

互联网校验和示例:加和两个 16 位整数

  • 数据 1: 11100110 01100110
  • 数据 2: 11010101 01010101
  • 求和结果 (普通加法): 1 \ 10111011 10111011 (第 17 位产生进位)
  • 回绕 (Wrap around): 将最高位的进位加到末尾 -> 10111011 10111100
  • 求反 (Checksum): 01000100 01000011 (此值即为最终校验和字段)
  • 注意:如果数字改变(位翻转)但加和恰好没变,校验和仍会通过,这就是所谓的“弱保护”。
  • 接收方动作
    1. 对接收到的报文段执行同样的求和计算。
    2. 将计算出的结果与校验和字段中的值进行比对。
    3. 判定
      • 如果不相等:说明检测到错误。
      • 如果相等:说明未检测到错误(但仍可能存在未被检测到的错位,即弱保护机制)。

5. 总结

UDP 虽然是“不可靠”的,但它的低延迟低开销使其成为互联网基建中不可或缺的一部分。对于想要极致控制传输行为的应用,UDP 是在应用层自定义协议逻辑的最完美起点。

3.4 可靠数据传输原则

可靠数据传输(Reliable Data Transfer, rdt)是网络中最基本且复杂的问题之一。可靠服务的抽象屏蔽了底层不可靠信道的复杂性。

1. 可靠服务的实现挑战

  • 抽象服务:应用层只需调用 rdt_send(),就认为数据能百分之百、按序到达目的地。
  • 底层现状:网络层(如 IP)提供的服务是不可靠的(丢包、位错误、乱序)。
  • rdt 协议的任务:通过控制逻辑屏蔽这些不可靠特征,向应用层呈现一个可靠的“虚拟信道”。

2. rdt 协议的逐步演进

rdt 1.0:完全可靠信道

  • 假设:底层信道没有任何位错误,也不会丢包。
  • 机制:发送方直接封装数据发送,接收方直接解封装接收。没有任何反馈。

rdt 2.0:可能有位错误的信道

  • 新机制
    • 校验和 (Checksum):用于检测数据包是否在传输中被损坏。
    • 确认 (ACK):接收方明确告知“收到了”。
    • 反面确认 (NAK):接收方通知“出错了,请重发”。
  • 控制策略停止-等待 (Stop-and-Wait)。发送方发完一个包后必须停下来等待接收方的反馈。

rdt 2.1 & 2.2:处理确认消息的损坏

  • 缺陷 (rdt 2.0):如果 ACK 或 NAK 消息在半路损坏了,发送方不知道接收方的真实状态,盲目重传会导致接收方收到重复包。
  • rdt 2.1 引入序列号 (Sequence Number)
    • 在每个包头添加序列号。
    • 对于停止-等待协议,只需要 0 和 1 两个数字交替即可。
    • 接收方可以通过序列号判断收到的包是“新包”还是“由于 ACK 丢失而重发的旧包”。
  • rdt 2.2 (无 NAK 协议):去掉 NAK。接收方对上一个成功接收的包发送冗余 ACK。发送方收到两个相同的 ACK 时,视为 NAK 并重传。

rdt 3.0:底层信道可能丢包

  • 新挑战:如果包丢了,接收方永远不会发 ACK,发送方会永远等待。
  • 核心机制:定时器 (Timer)
    • 发送方设定一个“合理”的超时时限。
    • 如果超时未收到 ACK,发送方假定包已经丢失,直接重传。
    • 序列号继续处理由于过早超时产生的重复包问题。

A. 回退 N 帧 (Go-Back-N, GBN)

  • 窗口机制:允许最多发送 N 个未确认的包。
  • 累积确认 (Cumulative ACK):ACK(n) 表示序号 n 的包都已经正确收到。
  • 超时处理:如果包 n 超时,重传 n 及其之后的所有包
  • 接收方:极其简单,只按序接收。收到乱序包直接丢弃,不予缓存。

B. 选择性重传 (Selective Repeat, SR)

  • 逐个确认:接收方对每个正确收到的包单独发送 ACK。
  • 独立重传:发送方为每一个发出的包设置独立的定时器。
  • 接收方缓存:可以接收并缓存乱序到达的包,直到凑齐顺序后统一交付给上层。
  • 窗口限制:窗口大小必须 序列号范围的一半,以避免由于循环序列号导致的旧包/新包混淆。

总结:可靠性传输就是一套“博弈”机制,通过复杂的序列号、确认应答和定时重传,在不可靠的流沙上搭建起坚固的基石。

3.5 面向连接的传输:TCP

3.6 拥塞控制原则

3.7 TCP拥塞控制

3.8 传输层功能的演变