第5章 传输层知识点整理
传输层处在应用层和网络层之间,是端到端通信体系中非常关键的一层。网络层解决的是主机到主机之间如何把分组送达的问题,而传输层进一步把通信对象细化到主机中的具体应用进程,使不同主机上的进程可以像直接通信一样交换数据。围绕这一目标,本章主要讨论传输层提供的服务、端口与套接字、无连接与面向连接服务,以及 UDP 和 TCP 两类典型传输层协议。

一、传输层在网络体系结构中的位置
从分层模型看,传输层位于网络层之上、应用层之下。网络层依靠 IP 地址实现主机到主机的通信,传输层则依靠端口号实现进程到进程的通信。也就是说,IP 地址能够定位某一台主机,端口号能够定位这台主机上的某一个应用进程,二者结合起来才能完整描述一次端到端通信的对象。
传输层只存在于通信双方的端系统中,路由器等中间设备通常只处理网络层及以下的信息,不需要分析传输层的完整语义。传输层协议把应用层交下来的数据封装成传输层报文段或用户数据报,再交给网络层处理;接收端的传输层从网络层得到数据后,根据端口号把数据交付给正确的应用进程。
传输层的核心价值可以概括为:它在不可靠的网络层服务之上,为应用进程提供更合适的通信服务。不同应用对可靠性、实时性、开销、连接管理的需求不同,因此传输层既提供面向连接、可靠的 TCP,也提供无连接、开销较小的 UDP。
二、传输层提供的主要服务
传输层提供的服务并不只是"把数据送到对方主机",它更强调进程之间的数据交付与通信质量控制。常见功能包括端到端通信、复用和分用、差错检测、可靠传输、流量控制、拥塞控制以及连接管理等。
1. 端到端的逻辑通信
传输层为运行在不同主机上的应用进程提供逻辑通信。所谓逻辑通信,是指从应用进程的角度看,发送方进程似乎可以直接把数据交给接收方进程,但实际的数据仍然要经过底层协议逐层封装、传输和解封装。
这种逻辑通信与网络层的主机到主机通信不同。网络层只关心把 IP 数据报从源主机送到目的主机,而传输层要进一步识别目的主机上的具体应用进程。正因为如此,传输层的寻址单位不是单独的 IP 地址,而是 IP 地址与端口号的组合。
2. 复用与分用
复用是指发送端多个应用进程可以共用同一个传输层协议向下发送数据。不同应用进程产生的数据被传输层加上相应的端口号等首部信息后,交给网络层封装发送。这样,一个主机上可以同时运行浏览器、邮件客户端、文件传输程序等多个网络应用,它们都可以通过传输层向外通信。
分用是指接收端的传输层根据报文中的目的端口号,把从网络层收到的数据交付给正确的应用进程。例如,目的端口号为 80 的 TCP 报文段通常会交给 HTTP 服务进程,目的端口号为 53 的 UDP 用户数据报通常会交给 DNS 服务进程。复用和分用使传输层能够支持一台主机上多个网络应用同时通信。
3. 差错检测
传输层可以通过校验和检测数据在传输过程中是否发生差错。UDP 和 TCP 都有校验和字段,用于检测传输层首部和数据部分在传输中是否出现比特差错。需要注意的是,校验和只能发现一部分差错,它本身不负责纠错;发现差错后如何处理,由具体协议决定。UDP 通常直接丢弃出错的数据报,而 TCP 会结合确认、重传等机制保证可靠交付。
4. 可靠传输
可靠传输是指传输层向应用层提供尽可能无差错、无丢失、无重复并且按序的数据交付。TCP 提供可靠传输服务,它通过序号、确认、超时重传、快速重传、校验和、接收窗口等机制,使应用层看到的是一个连续、有序、可靠的字节流。
UDP 不提供可靠传输。它只是在 IP 的基础上增加端口号和校验和等简单功能,不负责确认、重传和排序。如果应用使用 UDP 又需要可靠性,就必须在应用层自己设计相应机制。
5. 流量控制
流量控制解决的是发送方发送速度与接收方接收能力之间的协调关系。如果发送方发送太快,而接收方应用进程来不及读取缓存中的数据,接收缓存可能被填满,从而造成数据丢失。TCP 通过接收方通告窗口控制发送方的未确认数据量,使发送方不会超过接收方当前的缓存承受能力。
流量控制关注的是接收端的处理能力和缓存空间,它与拥塞控制不同。即使网络路径很空闲,如果接收方缓存不足,也需要降低发送速度;反过来,即使接收方缓存充足,如果网络中出现拥塞,也需要通过拥塞控制限制发送速率。
6. 拥塞控制
拥塞控制解决的是网络内部资源不足时如何避免过多数据继续注入网络。路由器缓存、链路带宽和处理能力都是有限的,当大量主机同时发送数据,网络中可能出现队列增长、时延增大、丢包增多等拥塞现象。TCP 通过拥塞窗口、慢开始、拥塞避免、快重传和快恢复等机制动态调节发送速率,尽量在提高吞吐量和避免网络拥塞之间取得平衡。
拥塞控制关注的是整个网络的承载能力,而不是接收端单个主机的缓存能力。TCP 实际发送窗口通常受到接收窗口和拥塞窗口的共同限制,即发送方能够发送的未确认数据量不能超过二者中的较小值。
三、传输层寻址、端口与套接字
1. 端口的作用
端口号用于标识主机中的应用进程。网络层通过 IP 地址找到目的主机后,传输层还需要根据端口号决定把数据交给哪个应用进程。端口号是传输层实现进程到进程通信的关键字段。
端口号是 16 位无符号整数,因此取值范围是 0 到 65535。按照使用范围,端口号通常分为以下几类:
| 端口类型 | 范围 | 主要用途 |
|---|---|---|
| 熟知端口 | 0 到 1023 | 分配给常见的标准服务,例如 HTTP、FTP、DNS 等 |
| 登记端口 | 1024 到 49151 | 分配给用户进程或应用程序使用,通常需要登记或约定 |
| 客户端临时端口 | 49152 到 65535 | 客户端发起通信时临时选择,通信结束后可释放 |
熟知端口使客户端可以方便地找到服务器端的标准服务。例如,Web 服务器通常监听 TCP 80 端口,DNS 服务器通常监听 UDP 53 端口。客户端通常不使用固定端口,而是由操作系统临时分配一个端口,用来区分不同的通信会话。
2. 常见应用层协议与端口
| 应用层协议或服务 | 常用端口 | 传输层协议 | 说明 |
|---|---|---|---|
| FTP 数据连接 | 20 | TCP | 用于传统主动模式下的数据传输 |
| FTP 控制连接 | 21 | TCP | 用于传输控制命令和响应 |
| TELNET | 23 | TCP | 远程登录服务 |
| SMTP | 25 | TCP | 电子邮件发送服务 |
| DNS | 53 | UDP 为主,必要时可用 TCP | 域名解析通常使用 UDP,区域传送或响应过大时可使用 TCP |
| TFTP | 69 | UDP | 简单文件传输,协议本身较轻量 |
| HTTP | 80 | TCP | Web 服务的传统默认端口 |
| SNMP | 161 | UDP | 网络管理协议常用端口 |
这些端口不是传输层服务的全部,只是典型例子。理解端口时要注意,端口号本身并不表示某个固定主机,而是表示某台主机上的某个应用进程或服务入口;同一个端口号在不同主机上可以分别对应各自的服务进程。
3. 套接字
套接字可以理解为网络通信端点的标识。在 TCP/IP 体系中,一个套接字通常由 IP 地址和端口号组成。对于一条 TCP 连接来说,仅知道一个端点还不够,需要由源 IP 地址、源端口号、目的 IP 地址和目的端口号共同唯一标识。
TCP 连接的端点是套接字,而不是单独的主机或单独的进程名称。这样的设计使同一台服务器可以同时与大量客户端建立连接。例如,很多客户端都可以访问同一个 Web 服务器的 80 端口,只要它们的源 IP 地址或源端口号不同,服务器就可以区分这些连接。
四、无连接服务与面向连接服务
传输层可以向应用层提供两类基本服务:无连接服务和面向连接服务。UDP 是无连接传输协议的代表,TCP 是面向连接传输协议的代表。
1. 无连接服务
无连接服务在发送数据前不需要建立连接。发送方可以直接把应用层数据封装成 UDP 用户数据报交给网络层发送,接收方收到后根据目的端口进行分用。UDP 不维护连接状态,也不保证数据一定到达、按序到达或只到达一次。
无连接服务的优点是开销小、时延低、实现简单,适合对实时性要求较高或能够容忍少量丢失的应用。例如 DNS 查询、简单网络管理、实时音视频、在线游戏中的部分数据传输等场景,常常会选择 UDP 或基于 UDP 的应用层协议。
2. 面向连接服务
面向连接服务在传输数据前需要先建立连接,通信结束后还要释放连接。TCP 通过三次握手建立连接,通过四报文挥手释放连接,并在连接期间维护序号、确认号、发送缓存、接收缓存、重传计时器、接收窗口、拥塞窗口等状态信息。
面向连接服务的主要优点是可靠、按序、面向字节流,适合文件传输、网页浏览、电子邮件等对数据完整性要求高的应用。它的代价是首部开销较大,需要维护连接状态,并且在建立连接和可靠传输过程中会引入一定时延。
五、UDP 的基本思想
UDP 的全称是用户数据报协议。它在 IP 提供的主机到主机交付基础上,增加了进程到进程交付和简单差错检测功能。UDP 不建立连接,不保证可靠交付,也不进行流量控制和拥塞控制,是一种轻量级传输层协议。
UDP 的主要特点可以从以下几个方面理解:
- UDP 是无连接的,通信前不需要握手,发送方可以直接发送用户数据报,因此启动开销很小。
- UDP 尽最大努力交付,不保证可靠性,不提供确认、重传、按序交付和重复消除。
- UDP 是面向报文的,应用层交给 UDP 多长的报文,UDP 就尽量按一个用户数据报发送,不会像 TCP 那样把数据看成连续字节流。
- UDP 没有拥塞控制,发送速率主要由应用层控制,因此适合某些实时应用,但也需要应用设计者避免过度占用网络资源。
- UDP 首部固定为 8 字节,比 TCP 的最小 20 字节首部更小,协议处理更简单。
- UDP 支持一对一、一对多、多对一和多对多通信,常用于广播、多播或请求响应模式的应用场景。
UDP 的"不可靠"并不等于"没有用"。很多应用更关注时延、实时性和应用层可控性,而不是由传输层强制保证每个字节都可靠到达。在这些场景下,UDP 的简单性反而是优势。
六、UDP 用户数据报
UDP 用户数据报由首部和数据两部分组成。UDP 首部非常简单,固定长度为 8 字节,包含源端口、目的端口、长度和校验和四个字段,每个字段长度都是 2 字节。

| 字段 | 长度 | 含义 |
|---|---|---|
| 源端口 | 16 位 | 标识发送端进程,接收方需要回信时使用;不需要时可以为 0 |
| 目的端口 | 16 位 | 标识接收端进程,是 UDP 分用的主要依据 |
| 长度 | 16 位 | 表示 UDP 首部和数据部分的总长度,最小值为 8 |
| 校验和 | 16 位 | 用于检测 UDP 首部和数据在传输中是否发生差错 |
UDP 的长度字段覆盖整个 UDP 用户数据报,而不是只表示数据部分长度。由于 UDP 首部固定为 8 字节,因此 UDP 数据部分长度等于 UDP 长度字段值减去 8。
UDP 是面向报文的,这意味着应用层一次交给 UDP 的数据会作为一个整体处理。如果应用层交给 UDP 的数据过大,交给 IP 层后可能发生 IP 分片。由于任何一个分片丢失都会导致整个原始数据报无法正确重组,因此实际应用中通常会控制 UDP 数据报大小,避免因分片带来额外风险。
七、UDP 校验和
UDP 校验和用于检测 UDP 用户数据报在传输过程中是否出现差错。计算校验和时,除了 UDP 首部和数据外,还要临时加入一个伪首部。伪首部并不会真正随 UDP 用户数据报发送,它只参与校验和计算,用来帮助检查数据是否被交付到了正确的源地址、目的地址和协议。

1. 伪首部的组成
UDP 伪首部通常包括源 IP 地址、目的 IP 地址、全 0 字段、协议号和 UDP 长度。其中,协议号用于标识上层协议,UDP 的协议号为 17。伪首部的作用不是扩展 UDP 首部,而是让校验和能够同时覆盖部分 IP 层关键信息,增强差错检测能力。
2. 校验和计算方法
UDP 校验和采用 16 位反码求和的方法。发送端计算时,先把伪首部、UDP 首部和数据按 16 位分组,若数据字节数为奇数,则在末尾补一个全 0 字节参与计算。随后对所有 16 位字进行反码加法,若最高位产生进位,则回卷加到最低位。最后对求和结果取反,得到校验和字段。
接收端校验时,同样把伪首部、UDP 首部和数据按 16 位反码求和。如果结果为全 1,通常认为没有检测到差错;如果不是全 1,则说明数据在传输过程中可能发生差错,接收端会丢弃该用户数据报。
3. 校验和的特点
UDP 校验和只能检测差错,不能纠正差错。它也不能保证所有差错都一定被发现,只是以较低开销提供了一种基本检测能力。在 IPv4 中,UDP 校验和在某些情况下可以不使用;而在 IPv6 中,UDP 校验和通常是必需的,因为 IPv6 首部本身不再提供首部校验和。
八、TCP 的基本特点

TCP 是传输控制协议,它提供面向连接、可靠、有序、全双工的字节流服务。与 UDP 相比,TCP 更复杂,但能为应用层屏蔽网络中的丢失、乱序、重复和差错,使应用层能够方便地处理连续数据流。
TCP 的主要特点包括:
- TCP 是面向连接的协议,数据传输前必须先建立连接,传输结束后需要释放连接。
- TCP 连接是点对点的,每条 TCP 连接只能有两个端点,不支持广播和多播。
- TCP 提供可靠交付,通过序号、确认、重传、校验和等机制保证数据正确到达。
- TCP 提供全双工通信,连接双方可以同时发送和接收数据,双方各自维护发送缓存和接收缓存。
- TCP 面向字节流,应用层交给 TCP 的数据会被看作连续字节序列,TCP 可以根据 MSS、窗口和网络状况把字节流划分成合适的报文段。
- TCP 具有流量控制和拥塞控制机制,既要考虑接收方缓存能力,也要考虑网络拥塞程度。
TCP 的"连接"并不是一条真实的物理链路,而是通信双方在端系统中维护的一组状态信息。中间路由器一般并不知道某条 TCP 连接的存在,它们只负责按照 IP 层规则转发分组。
九、TCP 报文段格式
TCP 报文段由首部和数据部分组成。TCP 首部最小长度为 20 字节,最大长度为 60 字节。首部长度不固定,是因为 TCP 可以携带选项字段,例如最大报文段长度、窗口扩大因子、时间戳和选择确认等。
| 字段 | 含义 |
|---|---|
| 源端口和目的端口 | 标识发送端和接收端应用进程 |
| 序号 | 表示本报文段数据部分第一个字节在字节流中的编号 |
| 确认号 | 表示期望收到的下一个字节编号,具有累计确认含义 |
| 数据偏移 | 表示 TCP 首部长度,单位为 4 字节 |
| 保留字段 | 供将来使用,通常置 0 |
| 控制位 | 包括 URG、ACK、PSH、RST、SYN、FIN 等标志 |
| 窗口 | 接收方通告的接收窗口大小,用于流量控制 |
| 校验和 | 检测 TCP 首部、数据和伪首部相关信息是否出错 |
| 紧急指针 | 与 URG 配合使用,指出紧急数据的结束位置 |
| 选项和填充 | 用于扩展功能,并保证首部长度为 4 字节的整数倍 |
1. 序号与确认号
TCP 把应用层数据看成连续的字节流,并为每个字节编号。某个 TCP 报文段的序号字段表示该报文段数据部分第一个字节的编号。如果一个报文段序号为 100,携带 200 字节数据,那么下一个数据字节的编号就是 300。
确认号表示接收方期望收到的下一个字节编号。例如,确认号为 300 表示编号 300 之前的所有字节都已经按序收到,接收方下一步希望收到从 300 开始的数据。TCP 使用累计确认方式,即一个确认号可以同时确认前面连续到达的一段数据。
SYN 和 FIN 虽然不一定携带应用数据,但在序号空间中各占用一个序号。因此,建立连接和释放连接时计算确认号要注意 SYN、FIN 对序号的影响。
2. 数据偏移与首部长度
数据偏移字段指出 TCP 数据部分从报文段的哪个位置开始,也就是 TCP 首部的长度。该字段以 4 字节为单位。由于 TCP 固定首部为 20 字节,因此没有选项时数据偏移值为 5;如果存在选项,数据偏移值会更大。TCP 首部最大长度为 60 字节,因此选项字段最大长度为 40 字节。
3. 控制位
TCP 首部中的控制位用于表达连接管理和数据处理含义:
| 控制位 | 含义 |
|---|---|
| URG | 紧急指针有效,表示报文段中包含紧急数据 |
| ACK | 确认号字段有效,连接建立后一般都置 1 |
| PSH | 请求接收方尽快把数据交给应用进程 |
| RST | 复位连接,通常用于异常终止或拒绝连接 |
| SYN | 用于建立连接,并同步双方初始序号 |
| FIN | 用于释放连接,表示发送方没有数据要发送 |
这些控制位经常组合使用。例如,建立连接时会出现 SYN 和 SYN+ACK;释放连接时会出现 FIN 和 ACK;异常情况下可能出现 RST。
4. 窗口字段
窗口字段用于流量控制,表示发送该报文段的一方当前愿意接收的字节数量。接收方通过通告窗口告诉发送方自己的缓存剩余能力,发送方据此控制未确认数据量。窗口值越大,说明接收方允许对方连续发送的数据越多;窗口值为 0 时,说明接收方暂时没有可用接收空间。
5. TCP 校验和
TCP 校验和与 UDP 校验和类似,也要计算伪首部、TCP 首部和数据。TCP 的协议号为 6。伪首部不随报文段传输,只参与校验和计算,用于增强端到端差错检测能力。与 UDP 不同,TCP 的校验和是必需的,是可靠传输机制的基础组成部分之一。
十、TCP 连接管理
TCP 连接管理包括连接建立、数据传输和连接释放三个阶段。连接建立的主要目标是让双方确认彼此的发送能力和接收能力,并协商初始序号;连接释放的目标是让双方都能有序结束数据发送,避免连接状态混乱和旧报文干扰。
1. 三次握手建立连接

TCP 连接建立通常采用三次握手。假设客户端主动发起连接,服务器被动等待连接,过程如下:
- 服务器先处于 LISTEN 状态,等待客户端连接请求。
- 客户端发送 SYN 报文段,SYN 置 1,选择初始序号 seq = x,随后进入 SYN-SENT 状态。
- 服务器收到后,发送 SYN+ACK 报文段,SYN 和 ACK 置 1,选择自己的初始序号 seq = y,并确认客户端的 SYN,ack = x + 1,随后进入 SYN-RCVD 状态。
- 客户端收到服务器的确认后,再发送 ACK 报文段,ACK 置 1,seq = x + 1,ack = y + 1,随后进入 ESTABLISHED 状态。
- 服务器收到最后一个 ACK 后,也进入 ESTABLISHED 状态,连接建立完成。
三次握手并不是简单地"多发一次报文",它有明确目的。第一次握手让服务器知道客户端能够发送;第二次握手让客户端知道服务器能够接收并发送;第三次握手让服务器知道客户端能够接收。这样,双方的发送和接收能力都得到确认。
三次握手还可以防止历史连接请求报文突然到达而造成错误连接。如果只用两次握手,服务器可能会因为收到一个过期的连接请求而建立连接,但客户端实际上并不需要该连接,造成资源浪费和状态混乱。
2. 四报文挥手释放连接
TCP 连接是全双工的,两个方向的数据流需要分别关闭。因此,一方没有数据要发送,并不意味着另一方也没有数据要发送。TCP 释放连接通常需要四个报文段。

假设客户端主动关闭连接,过程如下:
- 客户端发送 FIN 报文段,表示自己没有数据要发送,随后进入 FIN-WAIT-1 状态。FIN 会占用一个序号。
- 服务器收到 FIN 后,发送 ACK 确认,随后进入 CLOSE-WAIT 状态。客户端收到该 ACK 后进入 FIN-WAIT-2 状态。此时客户端到服务器方向的数据流已经关闭,但服务器仍可继续向客户端发送数据。
- 服务器数据发送完毕后,发送 FIN 报文段,进入 LAST-ACK 状态。
- 客户端收到服务器的 FIN 后,发送 ACK 确认,进入 TIME-WAIT 状态。
- 服务器收到最后的 ACK 后进入 CLOSED 状态。客户端等待 2MSL 后也进入 CLOSED 状态。
连接释放通常是四个报文段,是因为 TCP 连接的两个方向需要独立关闭。服务器对客户端 FIN 的确认和服务器自己的 FIN 可能不是同时发送的,中间可能还要继续传输剩余数据。
3. TIME-WAIT 状态的意义
主动关闭方在发送最后一个 ACK 后不会立即关闭,而是进入 TIME-WAIT 状态并等待 2MSL。这样做有两个重要原因。
第一,保证最后一个 ACK 能够被对方收到。如果最后的 ACK 丢失,被动关闭方会重发 FIN,主动关闭方仍处于 TIME-WAIT 状态,就可以再次发送 ACK。
第二,让本连接中可能滞留在网络中的旧报文段自然消失,避免它们干扰之后使用相同端口组合的新连接。MSL 是报文段在网络中允许存在的最长时间,等待 2MSL 可以较充分地清理旧报文影响。
十一、TCP 可靠传输
TCP 的可靠传输建立在字节编号、累计确认、差错检测、重传机制和滑动窗口的基础上。它把复杂的不可靠网络环境转化为应用层看到的可靠字节流。
1. 序号机制
TCP 给每个字节编号,而不是只给每个报文段编号。报文段中的序号表示该报文段第一个数据字节的编号。通过字节编号,接收方可以判断数据是否按序到达、是否存在缺失,也可以在重传时准确定位缺失的数据范围。
初始序号不是固定从 0 开始,而是在连接建立时由双方各自选择。这样可以降低旧连接报文段与新连接数据混淆的可能性。
2. 确认机制
TCP 使用确认号表示接收方期望收到的下一个字节。确认具有累计性,即确认号之前的连续数据都已经收到。例如,接收方发送 ack = 501,表示它已经正确收到 500 号及以前的所有字节,下一步期待从 501 开始的数据。
累计确认简化了协议处理,但也意味着当中间某个报文段丢失时,接收方即使收到了后续报文段,也会不断重复确认缺失位置之前的最后连续字节。发送方可以利用重复 ACK 判断可能发生了丢失。
3. 重传机制
TCP 通过重传处理丢失或出错的数据。常见重传方式包括超时重传和快速重传。
超时重传依赖重传计时器。发送方发出报文段后启动计时器,如果在超时时间内没有收到相应确认,就认为该数据可能丢失,重新发送。超时时间不能过短,否则会造成不必要重传;也不能过长,否则丢失恢复太慢。因此 TCP 会根据往返时延 RTT 的估计动态调整超时时间。
快速重传利用重复 ACK。当发送方连续收到多个相同确认号的 ACK,通常说明接收方一直在等待某个缺失报文段。典型情况下,发送方收到 3 个重复 ACK 后,不必等到超时就立即重传缺失的报文段,从而提高丢失恢复速度。
4. 校验和与丢弃
TCP 接收端会检查校验和。如果报文段校验失败,接收端会丢弃该报文段。发送端不会直接知道"校验失败"这一事实,而是通过迟迟收不到对应确认,或者通过重复 ACK 等现象触发重传。
5. 滑动窗口与流水线传输
TCP 不采用简单的停等方式,而是使用滑动窗口允许发送方连续发送多个报文段。只要未确认数据量没有超过发送窗口,发送方就可以继续发送,这提高了链路利用率和吞吐量。
滑动窗口的大小受到接收窗口和拥塞窗口共同限制。接收窗口来自接收方的缓存能力,拥塞窗口来自发送方对网络拥塞程度的判断。发送窗口随确认到达向前滑动,使新的数据可以继续发送。
十二、TCP 流量控制
TCP 流量控制的目标是防止发送方过快发送数据导致接收方缓存溢出。接收端为每条 TCP 连接分配接收缓存,应用进程从缓存中读取数据。如果应用进程读取较慢,缓存可用空间会减少,接收方就要通过窗口字段向发送方通告较小的接收窗口。

1. 接收窗口
接收窗口 rwnd 表示接收方当前还能接收多少字节。发送方必须保证已发送但尚未确认的数据量不超过接收方通告的 rwnd。可以用如下关系理解:
发送方已发送但尚未确认的数据量 = LastByteSent - LastByteAcked
只有当这个值不超过接收窗口时,发送方才不会压垮接收端缓存。
2. 零窗口与持续计时器
当接收方缓存没有剩余空间时,可以通告窗口值为 0,要求发送方暂时停止发送普通数据。之后如果接收方应用进程读取了数据,缓存腾出空间,需要通知发送方新的窗口大小。
如果窗口更新报文丢失,双方可能陷入等待:接收方认为自己已经通知了新窗口,发送方却仍认为窗口为 0。为避免这种情况,TCP 使用持续计时器,让发送方在零窗口期间偶尔发送窗口探测报文,以便及时获知接收方窗口是否已经重新打开。
3. 流量控制与可靠传输的关系
流量控制本身并不直接保证数据可靠,但它与可靠传输密切相关。发送方通过窗口限制未确认数据量,接收方通过缓存和确认机制组织数据交付。窗口过小会限制吞吐量,窗口过大又可能超过接收方能力,因此 TCP 需要根据接收方通告动态调整发送行为。
十三、TCP 拥塞控制
拥塞控制的目标是避免网络中同时存在过多未确认数据,导致路由器队列过长、时延增大和分组丢失。TCP 拥塞控制是端到端实现的,发送方根据 ACK 到达情况、丢包和超时等信号推断网络拥塞程度,并调整拥塞窗口 cwnd。
1. 拥塞窗口与发送窗口
拥塞窗口 cwnd 是发送方根据网络状况维护的窗口,用来限制向网络中注入的数据量。TCP 实际可发送的未确认数据量通常不超过接收窗口 rwnd 和拥塞窗口 cwnd 的较小值:
发送窗口 = min(rwnd, cwnd)
如果接收方缓存很小,rwnd 成为限制因素;如果网络拥塞严重,cwnd 成为限制因素。这个关系体现了 TCP 同时进行流量控制和拥塞控制。
2. 慢开始
慢开始用于连接刚建立或发生严重拥塞后的阶段。开始时,发送方把 cwnd 设置得较小,通常以 1 个 MSS 为起点。每收到一个新的 ACK,cwnd 增加 1 个 MSS。由于一个 RTT 内可能收到多个 ACK,因此从每个 RTT 的整体效果看,cwnd 近似按指数增长。
慢开始的名称容易造成误解。它并不是一直很慢,而是从小窗口开始快速探测网络可用容量。为了避免增长过快,TCP 使用慢开始门限 ssthresh。当 cwnd 增长到 ssthresh 后,进入拥塞避免阶段。
3. 拥塞避免
拥塞避免阶段让 cwnd 线性增长。典型效果是每经过一个 RTT,cwnd 大约增加 1 个 MSS。相比慢开始的指数增长,拥塞避免更加谨慎,用来在接近网络可承载能力时逐步探测可用带宽。
拥塞避免体现了加性增大的思想:网络没有表现出拥塞时,发送方缓慢增加发送速率,以提高吞吐量;一旦检测到丢包或超时,就认为网络可能发生拥塞,需要降低发送速率。
4. 超时后的处理
如果发生超时,TCP 通常认为网络拥塞较严重。常见处理方式是把 ssthresh 设置为当前 cwnd 的一半,然后把 cwnd 降为 1 个 MSS,重新进入慢开始阶段。这样做会显著降低发送速率,给网络缓冲和链路资源恢复的机会。
这种策略体现了乘性减小思想:一旦发生拥塞信号,就把发送窗口大幅降低,而不是只减少一点点。加性增大和乘性减小合称 AIMD,是 TCP 拥塞控制的重要思想。
5. 快重传
当接收方发现中间某个报文段缺失,但后续报文段陆续到达时,会不断发送针对缺失位置的重复 ACK。发送方如果连续收到 3 个重复 ACK,就可以推断某个报文段很可能丢失,于是立即重传该报文段,而不必等待重传计时器超时。
快重传可以显著缩短单个报文段丢失后的恢复时间,尤其是在网络仍然能够传递后续报文段的情况下。它说明网络不一定完全阻塞,可能只是个别报文段丢失,因此处理策略可以比超时更温和。
6. 快恢复
快恢复通常与快重传配合使用。发送方收到 3 个重复 ACK 后,认为网络发生了轻度拥塞,但因为仍能收到 ACK,说明网络还有一定传输能力。此时 TCP 不一定把 cwnd 降到 1 个 MSS,而是把 ssthresh 设置为当前 cwnd 的一半,并将 cwnd 调整到与 ssthresh 相关的值,随后进入拥塞避免阶段。
快恢复避免了每次丢包都回到慢开始的低速状态,使 TCP 在出现少量丢包时能够更平滑地恢复传输。不同 TCP 版本在快恢复细节上可能不同,但核心思想都是:收到多个重复 ACK 时,降低窗口但不完全从头开始。
7. 拥塞控制状态变化
TCP 拥塞控制可以概括为以下过程:
- 连接开始时使用慢开始,cwnd 从较小值起步并指数增长。
- 当 cwnd 达到 ssthresh 后进入拥塞避免,cwnd 线性增长。
- 若出现超时,说明拥塞可能较严重,ssthresh 变为当前窗口的一半,cwnd 降为 1 个 MSS,重新慢开始。
- 若收到 3 个重复 ACK,触发快重传和快恢复,ssthresh 变为当前窗口的一半,cwnd 适当降低后进入拥塞避免。
这种机制使 TCP 能够不断探测网络容量:可用容量看起来充足时逐渐增大发送速率,出现拥塞信号时主动降低发送速率。
十四、TCP 与 UDP 的对比
TCP 和 UDP 都位于传输层,都使用端口号实现进程到进程通信,也都可以使用校验和检测差错。但二者面向的应用需求不同。
| 对比项 | UDP | TCP |
|---|---|---|
| 连接方式 | 无连接,发送前不握手 | 面向连接,传输前需要建立连接 |
| 可靠性 | 不保证可靠交付 | 提供可靠、按序、不重复的字节流 |
| 数据形式 | 面向报文,保留应用层报文边界 | 面向字节流,不保留应用层报文边界 |
| 首部开销 | 固定 8 字节 | 最小 20 字节,最大 60 字节 |
| 流量控制 | 不提供 | 提供接收窗口机制 |
| 拥塞控制 | 不提供 | 提供慢开始、拥塞避免、快重传、快恢复等机制 |
| 适用场景 | 实时性强、开销敏感、应用可自控的场景 | 对可靠性和完整性要求高的场景 |
| 典型应用 | DNS、TFTP、SNMP、实时音视频等 | HTTP、FTP、SMTP、TELNET 等 |
选择 TCP 还是 UDP,并不是简单地看哪个"更好",而是取决于应用需求。需要可靠、顺序和完整交付时通常选择 TCP;需要低时延、低开销或应用层自定义控制时,UDP 更灵活。
十五、本章知识脉络
传输层的主线可以从"服务对象"和"服务方式"两个角度把握。服务对象从网络层的主机扩展到应用进程,因此端口、套接字、复用和分用是理解传输层的基础。服务方式则分为无连接和面向连接,对应 UDP 和 TCP 两种典型协议。
UDP 的关键在于简单。它只提供端口分用和基本差错检测,不建立连接,不保证可靠性,也不控制发送速率。理解 UDP 时,要抓住固定 8 字节首部、面向报文、校验和伪首部和应用层自控这些要点。
TCP 的关键在于可靠和控制。它通过连接管理建立双方状态,通过序号和确认实现有序交付,通过重传机制应对丢失,通过接收窗口实现流量控制,通过拥塞窗口和相关算法实现拥塞控制。理解 TCP 时,应把报文段首部、三次握手、四报文挥手、可靠传输、流量控制和拥塞控制联系起来,而不是把它们看成彼此孤立的知识点。
传输层最终体现的是网络协议设计中的取舍:UDP 追求简单、快速和应用层灵活性,TCP 追求可靠、稳定和通用性。两者共同支撑了互联网中大量不同类型的应用通信。
重点问题






