Network - 02.Transport Layer-01
- 在两个端点(主机)上运行的应用程序进程之间建立、管理和终止通信会话。这与网络层负责主机之间的通信形成对比。
- 网络层 (主机到主机): 负责将数据包从源主机路由到目的主机,使用 IP地址 进行寻址。例如,你的电脑向Google的服务器发送一个请求。
- 传输层 (进程到进程): 负责将数据从源主机上的特定进程交付到目的主机上的特定进程,使用 端口号 进行寻址。例如,你的浏览器进程 (端口号 12345) 向Google服务器上的Web服务器进程 (端口号 80 或 443) 发送请求。
- 可靠数据传输 (Reliable Data Transfer - RDT): 确保数据完整、按序到达。这是 TCP 协议的核心功能 。
- 连接管理: 建立和拆除连接(例如 TCP 的三次握手和四次挥手) 。
- 流量控制 (Flow Control): 防止发送方的数据淹没接收方 。
- 拥塞控制 (Congestion Control): 防止网络过载(例如 AIMD、慢启动) 。
- 多路复用/解复用: (通过 TCP/UDP 隐含) 使用端口号将数据交付给正确的应用程序进程。
- 差错检测: 使用校验和 (Checksum) 检查数据在端到端传输中是否出错
一、传输层概述 (Transport Layer Services)
1.1 学习目标 (Goals)
- 理解传输层服务背后的原理 (Principles)
- 多路复用 (Multiplexing) / 多路分用 (Demultiplexing)
- 可靠数据传输 (Reliable Data Transfer)
- 流量控制 (Flow Control)
- 拥塞控制 (Congestion Control)
- 学习互联网中的传输层协议 (Protocols)
- UDP: 无连接传输 (Connectionless Transport)
- TCP: 面向连接的传输 (Connection-oriented Transport)
- TCP 拥塞控制 (TCP Congestion Control)
1.2 传输层的核心功能
- 传输层协议为运行在不同主机上的应用进程 (Application Processes) 之间提供逻辑通信 (Logical Communication)。
- 传输协议只运行在端系统 (End Systems) 中。
- 发送方 (Send Side): 将应用层的报文 (Messages) 分割成报文段 (Segments),然后传递给网络层。
- 接收方 (Rcv Side): 将接收到的报文段重组成报文,并传递给应用层。
- 互联网为应用提供了多种传输协议,主要是 TCP 和 UDP。
1.3 传输层 vs. 网络层 (Transport vs. Network Layer)
- 网络层 (Network Layer): 提供主机 (Hosts) 之间的逻辑通信。
- 传输层 (Transport Layer): 提供进程(Processes) 之间的逻辑通信。 它依赖于网络层提供的服务,并对其进行增强。
- 12个孩子之间互相写信。
- 进程 (Processes) = 孩子们 (Kids)
- 应用报文 (App Messages) = 信封里的信件 (Letters)
- 主机 (Hosts) = 房子 (Houses)
- 传输层协议 = Ann 和 Bill(负责在屋里收发信件,确保信件交给正确的孩子)。
- 网络层协议 = 邮政服务 (Postal Service)(负责在房子之间传递信件)。
1.4 互联网协议栈中的数据单位
| 协议层 | 数据基本单位 |
|---|---|
| 应用层 (Application Layer) | 消息 (Message) |
| 传输层 (Transport Layer) | 数据段 (Segment) |
| 网络层 (Network Layer) | 数据包 (Datagram) |
| 链路层 (Link Layer) | 数据帧 (Frame) |
| 物理层 (Physical Layer) | 符号 (Symbol)、比特 (Bit) |
二、多路复用与多路分用 (Multiplexing and Demultiplexing)
- 多路分用 (Demultiplexing): 在接收方主机,将收到的报文段根据头部信息分发给正确的套接字 (Socket)。
- 多路复用 (Multiplexing): 在发送方主机,从多个套接字收集数据,并为每个数据块封装上头部信息(用于后续的分用),然后传递给网络层。
定义与角色
套接字是应用层与传输层之间的编程接口 (API)。它是应用程序进程与网络协议栈进行数据交换的“门户”。形象比喻
如果把网络通信比作寄信:- 进程是房子里的人。
- 套接字就是房子的门。
- 发送数据时,进程把报文推过这扇“门”,之后就由门外的运输部门(TCP/UDP)负责投递。
寻址标识
一个套接字通常由 IP 地址(标识主机)和 端口号(标识进程)共同唯一确定。- Socket = (IP Address : Port Number)
主要类型
- TCP 套接字 (Stream Socket): 提供面向连接、可靠的字节流服务。
- UDP 套接字 (Datagram Socket): 提供无连接、不可靠的数据报服务。
2.1 分用是如何工作的
主机使用 IP 地址 和 端口号 (Port Numbers) 将报文段定向到正确的套接字。
- 每个数据报 (Datagram) 都包含源 IP 地址和目的 IP 地址。
- 每个数据报携带一个传输层报文段 (Segment)。
- 每个报文段都包含源端口号 (Source Port #) 和目的端口号 (Dest Port #)。
2.2 无连接分用 (Connectionless Demultiplexing - UDP)
- 一个 UDP 套接字由一个包含两个元素的元组 (Two-tuple) 来标识:
(目的IP地址, 目的端口号)。 - 当主机收到一个 UDP 报文段时,它检查报文段中的目的端口号,并将其定向到绑定该端口号的套接字。
- 因此,来自不同源 IP 地址或源端口号的 IP 数据报,只要它们的目的端口号相同,都会被定向到同一个 UDP 套接字。
2.3 面向连接的分用 (Connection-oriented Demultiplexing - TCP)
- 一个 TCP 套接字socket由一个包含四个元素的元组 (Four-tuple) 来标识:
(源IP地址, 源端口号, 目的IP地址, 目的端口号)。 - 接收方主机会使用这全部四个值来将报文段定向到正确的套接字。
- 这意味着服务器可以为每一个连接的客户端维护一个独立的套接字,每个套接字都由其唯一的四元组标识。
三、无连接传输: UDP (User Datagram Protocol)
UDP 是一种 “精简” 或 “最基本” 的互联网传输协议。
3.1 UDP 的特点
- 尽力而为 (Best Effort): UDP 报文段可能会丢失 (Lost) 或乱序 (Delivered out of order) 到达。
- 无连接 (Connectionless): 在数据传输前,发送方和接收方之间没有握手 (Handshaking) 过程。 每个 UDP 报文段都是独立处理的。
- 为什么需要 UDP?
- 无连接建立延迟: 省去了建立连接所需的时间。
- 简单: 发送方和接收方无需维护连接状态。
- 头部开销小: UDP 的头部只有 8 字节,非常小。
- 无拥塞控制: UDP 可以按照应用期望的速率发送数据,不会被拥塞控制限制。
3.2 UDP 的应用
- 常用于流媒体应用 (Streaming Multimedia Apps),因为这类应用能容忍部分数据丢失 (Loss Tolerant),但对传输速率敏感 (Rate Sensitive)。
- 其他用途包括 DNS 和 SNMP。
- 如果需要在 UDP 上实现可靠传输,必须在应用层 (Application Layer) 增加可靠性机制。
3.3 UDP 报文段格式与校验和 (Checksum)
- 准备数据
- 分块: 将所有需要校验的数据(例如 TCP 头部 + TCP 数据 + 伪首部)在逻辑上划分为 16 位(2 字节)的块。
- 补齐: 如果数据的总字节数是奇数,就在末尾(逻辑上)补一个全 0 的字节 (0x00),使其成为偶数,以便能配成 16 位的块。
- 清零: 将数据中用于存放“校验和”的字段(例如 TCP 头部中的 Checksum 字段)全部设为 0。
- 计算 1 的补码和
- 相加: 将所有 16 位的块看作无符号整数,进行二进制加法。
- 回卷 (Wrap Around): 1 的补码加法有一个关键特性:如果两个 16 位的数相加产生了第 17 位(即发生了溢出或“进位”),这个进位不能丢弃。您必须将这个进位(值总为 1)加回到总和的最低位。这个过程称为**“回卷” (end-around carry)**。
- 迭代: 持续进行回卷操作,直到所有的进位都被加回去,最终的总和是一个 16 位的数。
- 取反
- 1 的补码: 对第 2 步得到的最终 16 位总和,按位取反(即 1 变成 0,0 变成 1)。
- 存入: 得到的结果就是最终的校验和。发送方将这个 16 位的值放入头部(例如 TCP 头部)的 Checksum 字段中,然后将数据包发送出去。
- 核心数学原理
在二进制反码算术中,一个数 与其反码 相加,结果的每一位都是 1(即全 1)。
- 公式:
- 接收端的“零开销”验证
取反操作使得接收端可以将校验和字段视为普通数据的一部分,直接参与整体加法运算,无需专门提取。
发送端: 发送
数据+~Sum。接收端: 计算
数据+~Sum。如果传输无误,这等价于计算Sum+~Sum。
- 效率提升
最终结果应为 全 1。在硬件电路中,检测“全 1”或“全 0”比比较两个数值更快速、更简单。
- UDP 头部: 包括源端口、目的端口、长度和校验和。
- 校验和 (Checksum): 用于检测传输过程中报文段出现的差错 (Errors),例如比特翻转。
- 发送方: 将报文段内容视为一系列16比特的整数,计算它们的反码和 (1’s Complement Sum)(将进位的1加在最低位上),并将结果存入校验和字段。
- 接收方: 对收到的报文段重新计算校验和,并与头部中的校验和字段进行比对。 如果不匹配,则检测到错误。
四、可靠数据传输原理 (Principles of Reliable Data Transfer - RDT)
目标:在不可靠的信道上实现可靠的数据传输。 这是网络领域最重要的十大主题之一。 我们将通过有限状态机 (FSM) 逐步构建可靠数据传输协议。
4.1 RDT 1.0: 可靠信道上的可靠传输
- 假设: 底层信道是完全可靠的,没有比特错误,也没有丢包。
- 实现: 发送方从上层接收数据,打包后发送;接收方从信道接收数据,解包后交付给上层。
4.2 RDT 2.0: 应对比特错误 (Channel with Bit Errors)
- 新情况: 底层信道可能会翻转数据包中的比特,但是不会有丢包。接收方必须要有发现错误的机制
- 解决方案: 引入错误检测和接收方反馈机制。
- 校验和 (Checksum): 用于检测比特错误。
- 确认 (Acknowledgements, ACKs): 接收方告知发送方数据包已成功接收,可以发送下一个数据包。
- 否定确认 (Negative Acknowledgements, NAKs): 接收方告知发送方数据包已损坏。
- 重传 (Retransmission): 发送方在收到 NAK 后,重传该数据包。
4.3 RDT 2.1 & 2.2: 应对损坏的ACK/NAK
- RDT 2.0 的致命缺陷: 如果 ACK 或 NAK 本身在传输中损坏了怎么办? 发送方无法确定接收方的状态,直接重传可能导致重复数据包 (Duplicate Packets)。
- 解决方案:
- RDT 2.1: 引入序列号 (Sequence Number)。 发送方为每个数据包添加序列号(如0和1交替)。 接收方通过检查序列号来判断是否是重复数据包,如果是则直接丢弃。
- RDT 2.2 (无 NAK 协议): 接收方只发送 ACK。 为了告知哪个包被正确接收,ACK 中必须包含被确认包的序列号。 如果发送方收到一个重复的 ACK,就执行与收到 NAK 相同的操作:重传当前数据包。
4.4 RDT 3.0: 应对丢包 (Packet Loss)
- 新情况: 底层信道不仅会出错,还可能丢失数据包(数据或ACK)。
- 解决方案: 引入定时器 (Countdown Timer)。
- 发送方在发送数据包后,启动一个定时器。
- 如果在定时器超时前没有收到对应的 ACK,就认为数据包丢失,并重传 (Retransmits) 该数据包。
- 序列号机制可以很好地处理因延迟而非丢失导致的重传(即重复包问题)。
- RDT 3.0 也被称为停等协议 (Stop-and-Wait Protocol)。
4.5 RDT 机制总结
为了在不可靠信道上实现可靠数据传输,最终的解决方案整合了四项核心机制:
- 校验和 (Checksum): 解决比特错误问题。
- 确认 (ACK): 提供接收方反馈。
- 序列号 (Sequence Number): 解决重复数据包问题。
- 定时器 (Timer): 解决丢包问题。
4.6 RDT 3.0 协议性能分析
rdt3.0 协议虽然实现了可靠传输,但其“停止-等待”(Stop-and-Wait)机制在现代网络(高带宽、高延迟)中性能极差,导致带宽资源被严重浪费。
1. 问题根源:停止-等待机制
- 工作模式: 发送方每发送一个数据包,就必须停止并等待接收方返回确认(ACK)后,才能发送下一个。
- 时间浪费: 在等待ACK返回的整个往返时间(RTT)内,发送方完全处于空闲状态,无法利用链路发送更多数据。
2. 实例量化分析
PPT中的例子生动地展示了这个问题:
- 场景: 在一个 1 Gbps 的高速链路上,往返延迟(RTT)为 30ms。
- 发送耗时 (
L/R): 发送一个数据包本身只需要 8微秒。 - 等待耗时 (
RTT): 而等待确认却需要 30,000微秒。 - 链路利用率 (
Utilization): 计算得出,发送方真正在发送数据的时间仅占整个周期的 0.027%。超过 99.9% 的时间里,高速链路都处于闲置状态。
五、流水线协议 (Pipelined Protocols)
5.1 停等协议的性能问题
RDT 3.0 (停等协议) 虽然能工作,但性能极差。 发送方在大部分时间里都在等待 ACK,导致链路利用率 (Utilization) 非常低。
5.2 流水线 (Pipelining)
- 核心思想: 允许发送方在收到 ACK 之前,连续发送多个数据包。 这就像流水线一样,让多个数据包同时处于“在途 (in-flight)”状态。
- 优点: 极大地提高了链路利用率。
- 要求:
- 需要更大的序列号范围。
- 发送方和/或接收方需要设置缓冲区 (Buffering)。
六、滑动窗口协议:回退N帧 (Go-Back-N) 与选择重传 (Selective Repeat)
流水线协议有两种通用形式:回退N帧 (Go-Back-N) 和选择重传 (Selective Repeat)。 它们都属于滑动窗口 (Sliding Window) 方法。
6.1 回退N帧 (Go-Back-N, GBN)
- 发送方:
- 维护一个大小为 N 的发送窗口,最多允许有 N 个未被确认的数据包在流水线中。
- 只为最老的、未被确认的数据包设置一个计时器。
- 当计时器超时,重传所有已发送但未被确认的数据包。
- 当接收到窗口最左端的包的ACK时,重置计时器并移动窗口,发送移动后的窗口中未发送的数据包。
- 当收到重复的ACK,直接无视。
- 接收方:
- 只发送累积确认 (Cumulative ACKs)。
ACK(n)表示序列号为 n 及 n 之前的所有数据包都已正确接收。 - 对于乱序到达的数据包,直接丢弃 (Discard),不进行缓存。 接收方会重新发送具有最高有序序列号的 ACK。
- 只发送累积确认 (Cumulative ACKs)。
6.2 选择重传 (Selective Repeat, SR)
- 发送方:
- 同样维护一个大小为 N 的发送窗口。
- 为每一个未被确认的数据包都维护一个独立的计时器。
- 当某个计时器超时,只重传那一个未被确认的数据包。
- 接收方:
- 对每一个正确接收的数据包都进行单独确认 (Individual ACKs)。
- 对于乱序到达的数据包,会将其缓存 (Buffers) 起来,直到所有缺失的数据包都到达,再按序交付给上层。
- 当收到在窗口前的数据包,可能因为之前发送的ACK损坏导致sender计时器超时,这时候再次发送ACK(n)。
- 发送方和接收方窗口不对齐,是因为sender尚未收到ACK
- 序列号空间的大小必须是窗口大小 () 的 至少两倍。
- 原因:如果序列号空间 (例如 N=3, 序列号 0,1,2),接收方无法区分一个序列号为 0 的分组是第一次发送的新包,还是一个迟到的重传包。
- 极端情况是发送方的的N个包都传到了接收方,但是接收方发送的所有ACK都丢包了。
6.3 GBN 与 SR 对比总结
| 对比项 | 回退N帧 (Go-Back-N) | 选择重传 (Selective Repeat) |
|---|---|---|
| 重传机制 | 重传所有已发送但未确认的帧。 | 只重传丢失或损坏的帧。 |
| 接收方行为 | 丢弃所有乱序的帧。 | 缓存乱序的帧,直到空缺被填补。 |
| 确认机制 | 累积确认 (Cumulative ACK)。 | 单独确认 (Individual ACK)。 |
| 复杂度 | 比较简单。 | 逻辑更复杂,发送和接收方都需要排序和存储。 |
| 适用场景 | 适用于网络条件好、误码率低的情况。 | 适用于网络条件差、误码率高的情况。 |
Network - 02.Transport Layer-01
https://yima-gu.github.io/2026/01/14/Network/Network-02-Transport-Layer-01/