传输层
约 4326 字大约 14 分钟
2025-07-27
传输层(Transport Layer)位于五层体系结构中的第四层,介于应用层和网络层之间,是承上启下的关键层次。其主要任务是为运行在不同主机上的应用进程提供端到端的逻辑通信服务。
- 向上:屏蔽网络层(IP)的不可靠性,为应用层提供可靠或不可靠的数据传输服务。
- 向下:利用网络层提供的服务,通过端口号标识不同的应用进程。
传输层的核心协议有 TCP(传输控制协议) 和 UDP(用户数据报协议) 两种。
一、TCP 与 UDP 对比
| 对比维度 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接 — 通信前需建立连接(三次握手),通信后释放连接(四次挥手) | 无连接 — 发送数据前无需建立连接,直接发送 |
| 数据传输单位 | 字节流(Byte Stream) — 将应用层数据视为无结构的字节流,按序号组织 | 报文(Message) — 保留应用层报文的边界,一次发送一个完整报文 |
| 通信方式 | 单播(Unicast) — 仅支持一对一通信 | 支持多播和广播 — 支持一对一、一对多、一对全 |
| 可靠性 | 可靠传输 — 通过序号、确认、重传等机制保证数据无丢失、无重复、按序到达 | 不可靠传输 — 尽最大努力交付(Best-effort),不保证可靠交付 |
| 流量控制 | ✅ 支持(滑动窗口) | ❌ 不支持 |
| 拥塞控制 | ✅ 支持(慢开始、拥塞避免、快重传、快恢复) | ❌ 不支持 |
| 首部开销 | 20~60 字节(较大) | 8 字节(固定、极小) |
| 传输效率 | 较低(需建立连接、确认、重传等) | 较高(无连接开销、无确认延迟) |
| 有序性 | 保证数据按发送顺序到达 | 不保证顺序,可能乱序到达 |
| 应用场景 | 文件传输(FTP)、网页浏览(HTTP/HTTPS)、电子邮件(SMTP)、远程登录(SSH) | 实时音视频(VoIP、直播)、在线游戏、DNS 查询、DHCP |
关键区别详解
1. 面向连接 vs 无连接
- TCP:通信双方在数据传输前必须通过三次握手建立连接,在传输结束后通过四次挥手释放连接。连接是逻辑上的端到端虚电路。
- UDP:发送方直接向目标 IP 和端口发送数据,不需要事先握手,也没有连接状态维护。
2. 字节流 vs 报文
- TCP:将应用层数据视为连续的字节流。TCP 可根据 MSS(最大报文段长度)对字节流进行分段,接收方按序号重组。不保留应用层消息的边界。
- UDP:保留应用层下发的报文边界。应用程序每次调用
sendto()发送的数据作为一个独立报文传递,接收方每次recvfrom()读取一个完整报文。
3. 单播 vs 多播/广播
- TCP:由于需要建立连接且维护序号和确认状态,只能支持一对一的单播通信。
- UDP:无连接特性使其天然支持一对多(多播/组播)和一对全(广播)通信,适用于视频会议、直播推流等场景。
4. 可靠 vs 不可靠
- TCP:通过序号(Sequence Number)、确认应答(ACK)、超时重传(RTO)、校验和、去重等机制,为应用层提供全双工的可靠字节流服务。
- UDP:仅提供校验和(可选),不保证数据一定到达、不保证按序到达、不保证不重复。可靠性由应用层自己保障。
二、端口号
端口号(Port Number)是传输层用于标识不同应用进程的地址,其核心作用是实现复用与分用。
| 属性 | 说明 |
|---|---|
| 长度 | 16 位(bit),取值范围 0~65535 |
| 本地意义 | 端口号只在本主机上有意义,不同主机可以使用相同端口号标识不同进程 |
| 功能 | 在传输层协议数据单元(TCP 报文段 / UDP 数据报)中标识发送方和接收方的应用进程 |
1. 复用与分用
- 复用(Multiplexing):发生在发送方。多个应用进程(如浏览器、邮件客户端、文件传输)的数据通过传输层协议封装后,共用底层的 IP 网络层发送出去。
- 分用(Demultiplexing):发生在接收方。传输层收到 IP 层上交的数据后,根据首部中的目的端口号将数据交付给对应的应用进程。
应用层: 进程A(80) 进程B(53) 进程C(443)
\ | /
传输层: 复用 → [TCP/UDP] ← 分用
|
网络层: IP2. 端口号分类
| 类别 | 范围 | 说明 |
|---|---|---|
| 熟知端口(Well-Known Ports) | 0~1023 | 由 IANA 分配,绑定标准服务。如 HTTP=80、HTTPS=443、DNS=53、SSH=22、FTP=21 |
| 注册端口(Registered Ports) | 1024~49151 | 可供用户或应用程序注册使用,如 MySQL=3306、Redis=6379 |
| 动态/私有端口(Dynamic/Private Ports) | 49152~65535 | 客户端临时使用,由操作系统动态分配,通信结束后释放 |
3. 套接字(Socket)
传输层通过 套接字 唯一标识一个通信端点:
套接字 = IP 地址 : 端口号一条 TCP 连接由 四元组 唯一标识:
(源 IP, 源端口, 目的 IP, 目的端口)三、TCP 首部格式
TCP 报文段的首部最小长度为 20 字节,最大为 60 字节(含选项字段)。其格式如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口(16) | 目的端口(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序号(Sequence Number, 32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号(Acknowledgment Number, 32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留 |U|A|P|R|S|F| 窗口大小(16) |
| (4) |(6) |R|C|S|S|Y|I| |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和(16) | 紧急指针(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(可选,可变长) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+各字段详解
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 | 16 bit | 发送方应用进程的端口号 |
| 目的端口 | 16 bit | 接收方应用进程的端口号 |
| 序号(Sequence Number, SEQ) | 32 bit | TCP 字节流中每个字节的编号。SYN=1 时,该字段为初始序号 ISN |
| 确认号(Acknowledgment Number, ACK) | 32 bit | 期望收到的下一个字节序号。ACK=1 时该字段有效 |
| 数据偏移 | 4 bit | 以 4 字节为单位,标识 TCP 首部长度(最小值 5 → 20B,最大值 15 → 60B) |
| 保留 | 6 bit | 保留供将来使用,目前必须为 0 |
| 控制位(Flags) | 6 bit | 详见下方表格 |
| 窗口大小(Window Size) | 16 bit | 接收方告知发送方自己还能接收多少字节数据(流量控制) |
| 校验和(Checksum) | 16 bit | 检验首部+数据部分的完整性(包含伪首部) |
| 紧急指针(Urgent Pointer) | 16 bit | URG=1 时有效,标识紧急数据末尾位置 |
| 选项(Options) | 可变(0~40B) | 如 MSS 选项、窗口缩放选项、SACK 等 |
控制位详解(Flags)
| 标志位 | 全称 | 含义 |
|---|---|---|
| URG | Urgent | 紧急指针有效,通知接收方优先处理紧急数据 |
| ACK | Acknowledgment | 确认号字段有效(建立连接后几乎总是置 1) |
| PSH | Push | 推送数据,要求接收方立即将数据交付应用层,不等待缓冲区填满 |
| RST | Reset | 重置连接。用于连接异常中断、拒绝非法连接请求等 |
| SYN | Synchronize | 同步序号。用于建立连接时同步初始序号(三次握手中的第一步) |
| FIN | Finish | 释放连接。发送方表示自己已经没有数据要发送了 |
序号与确认号的工作机制
- 序号(SEQ):TCP 将应用层字节流中的每个字节都编号。报文段的序号是本报文段第一个字节的序号。
- 确认号(ACK):期望接收到的下一个字节的序号。例如接收方收到序号为 501 的 100 字节数据,则确认号为 601。
发送方: 数据[1:100] 数据[101:200] 数据[201:300]
SEQ=1 SEQ=101 SEQ=201
↓ ↓ ↓
接收方: ACK=101 ACK=201 ACK=301四、UDP 首部格式
UDP 数据报的首部长度固定为 8 字节,结构非常简洁。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口(16) | 目的端口(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 长度(16) | 校验和(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+各字段详解
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 | 16 bit | 发送方端口号(可选,不需要时可置 0) |
| 目的端口 | 16 bit | 接收方端口号(必须,用于分用) |
| 长度 | 16 bit | UDP 数据报总长度(首部+数据),单位为字节。最小值为 8(无数据时) |
| 校验和 | 16 bit | 检测数据报在传输中是否出错(可选,UDPv4 中可不使用,置 0) |
UDP 首部特点
- 固定 8 字节:没有选项字段,首部开销极小。
- 无序号和确认号:无需可靠传输,故不包含序号、确认号等字段。
- 无窗口字段:没有流量控制和拥塞控制,发送速率不受接收方限制。
- 校验和可选:在 IPv4 中校验和可以置 0 表示不校验;IPv6 中校验和是必选的。
UDP 校验和计算(伪首部)
UDP 的校验和覆盖首部 + 数据 + 伪首部(Pseudo Header)。伪首部不是数据报的一部分,仅用于校验计算,包含:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源 IP 地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的 IP 地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0 | 17(UDP) | UDP 段长度(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+伪首部的引入使得 UDP 能检测数据是否被错误地传递给了错误的 IP 地址。
五、TCP 核心机制
1. 可靠传输机制
TCP 通过以下机制确保数据无差错、不丢失、不重复、按序到达:
| 机制 | 说明 |
|---|---|
| 序号(Sequence Number) | 为每个字节编号,接收方据此排序和去重 |
| 确认应答(ACK) | 接收方收到数据后发送确认,告知发送方哪些数据已成功接收 |
| 超时重传(Retransmission) | 发送方启动定时器,超时未收到 ACK 则重传数据 |
| 快速重传(Fast Retransmit) | 收到 3 个重复 ACK 时立即重传,不等超时 |
| 校验和(Checksum) | 检测数据在传输中是否损坏,损坏则丢弃 |
| 去重 | 接收方通过序号丢弃重复到达的报文段 |
超时重传时间(RTO)自适应
TCP 根据网络状况动态计算 RTO,采用 Jacobson 算法:
EstimatedRTT = (1 - α) × EstimatedRTT + α × SampleRTT (α = 0.125)
DevRTT = (1 - β) × DevRTT + β × |SampleRTT - EstimatedRTT| (β = 0.25)
RTO = EstimatedRTT + 4 × DevRTT2. 流量控制(Flow Control)
流量控制的目的是让接收方控制发送方的发送速率,防止发送方发送过快导致接收方缓冲区溢出。
实现方式:滑动窗口协议(Sliding Window Protocol)
发送方: 已确认 |←──── 可用窗口 ────→| 已发送但未确认 | 待发送
↑
窗口大小
接收方: 已消费 |←── 已接收未消费 ──→|←── 可用空间 ──→|
↑
rwnd(窗口通告)- 接收方在 TCP 首部的窗口(Window Size) 字段中填入自己当前的空闲缓冲区大小(rwnd)。
- 发送方根据 rwnd 调整发送窗口,确保已发送但未确认的数据量不超过 rwnd。
- 若接收方通告 rwnd = 0,发送方停止发送,但会定期发送 窗口探测(Window Probe) 报文。
注意:流量控制是端到端的,调节的是发送方 vs 接收方之间的速率,与网络中间节点无关。
3. 拥塞控制(Congestion Control)
拥塞控制的目的是防止过多数据注入网络,避免网络中的路由器或链路过载。TCP 通过发送方维护一个拥塞窗口(cwnd) 来限制发送速率,实际发送窗口取 min(cwnd, rwnd)。
TCP 拥塞控制包含四种算法:
① 慢开始(Slow Start)
- 连接刚建立时,cwnd 初始为 1 个 MSS(最大报文段长度)。
- 每收到一个 ACK,cwnd 翻倍(指数增长)。
- 当 cwnd ≥ 慢开始门限(ssthresh) 时,转入拥塞避免阶段。
cwnd 增长过程: 1 → 2 → 4 → 8 → 16 → ...
(每轮 RTT 翻倍)② 拥塞避免(Congestion Avoidance)
- cwnd 每次 RTT 增加 1 个 MSS(线性增长,加法增大 AI)。
- 当发生丢包(超时重传)时,执行乘法减小(MD):
- ssthresh = cwnd / 2
- cwnd = 1(重新慢开始)
③ 快重传(Fast Retransmit)
- 接收方收到乱序报文时,立即发送重复 ACK(告知缺失的序号)。
- 发送方收到 3 个重复 ACK,不等超时立即重传丢失报文。
④ 快恢复(Fast Recovery)
- 快重传后,执行:
- ssthresh = cwnd / 2
- cwnd = ssthresh(直接进入拥塞避免,而非回到慢开始)
拥塞控制状态机:
连接建立
↓
┌──────────┐ cwnd ≥ ssthresh ┌──────────────┐
│ 慢开始 │ ──────────────────→ │ 拥塞避免 │
│ (指数增长) │ │ (线性增长) │
└─────┬────┘ └──────┬───────┘
│ │
超时重传│ 3个重复ACK
│ │
↓ ↓
ssthresh = cwnd/2 ┌──────────────┐
cwnd = 1 │ 快恢复 │
─────→ 慢开始 │ cwnd=ssthresh│
└──────┬───────┘
│
拥塞避免(线性增长)AIMD(加法增大乘法减小) 是 TCP 拥塞控制的核心理念:
- 加法增大(Additive Increase):拥塞避免阶段 cwnd 缓慢线性增长,探测可用带宽。
- 乘法减小(Multiplicative Decrease):检测到拥塞后大幅减小 cwnd,快速释放网络资源。
拥塞控制 vs 流量控制
| 维度 | 流量控制 | 拥塞控制 |
|---|---|---|
| 控制对象 | 接收方的处理能力 | 整个网络的承载能力 |
| 参与者 | 发送方 ↔ 接收方(端到端) | 发送方根据网络状况调整 |
| 窗口依据 | rwnd(接收窗口) | cwnd(拥塞窗口) |
| 实际窗口 | min(cwnd, rwnd) |
4. 连接管理 — 三次握手(Three-Way Handshake)
TCP 建立连接需要三次握手,目的是同步初始序号(ISN) 并协商通信参数(如 MSS、窗口缩放因子)。
Client Server
| |
|──────── SYN, SEQ=x ──────────→| Step 1: 客户端发送 SYN 报文
| | 客户端进入 SYN_SENT 状态
| |
|←────── SYN, SEQ=y, ACK=x+1 ───| Step 2: 服务端回复 SYN+ACK
| | 服务端进入 SYN_RCVD 状态
| |
|──────── ACK, SEQ=x+1 ────────→| Step 3: 客户端发送 ACK
| | 双方进入 ESTABLISHED 状态
| |三次握手流程
| 步骤 | 报文 | 作用 | 状态变化 |
|---|---|---|---|
| ① | 客户端 → 服务端:SYN=1, seq=x | 客户端请求建立连接,同步初始序号 x | CLOSED → SYN_SENT |
| ② | 服务端 → 客户端:SYN=1, seq=y, ACK=1, ack=x+1 | 服务端同意连接,发送自己的 ISN=y,确认收到客户端的 ISN | LISTEN → SYN_RCVD |
| ③ | 客户端 → 服务端:ACK=1, seq=x+1, ack=y+1 | 客户端确认收到服务端的 ISN,完成建立 | SYN_SENT → ESTABLISHED |
为什么是三次而不是两次?
如果只有两次握手,服务端无法区分"客户端发送的 SYN 是新的连接请求"还是"延迟到达的旧 SYN 报文"。三次握手通过客户端的第三次 ACK 确认,确保连接建立在新鲜且有效的请求之上,防止"已失效的连接请求"导致资源浪费。
5. 连接管理 — 四次挥手(Four-Way Wavehand)
TCP 释放连接需要四次挥手,因为 TCP 连接是全双工的,每一方的数据流都需要独立关闭。
Client Server
| |
|──────── FIN, SEQ=u ─────────→| Step 1: 客户端发送 FIN
| | 客户端进入 FIN_WAIT_1
| |
|←────── ACK, SEQ=v, ACK=u+1 ──| Step 2: 服务端发送 ACK
| | 服务端进入 CLOSE_WAIT
| | 客户端进入 FIN_WAIT_2
| (半关闭状态:客户端 → 服务端已关闭, |
| 服务端 → 客户端仍可继续发送数据) |
| |
|←────── FIN, SEQ=w, ACK=u+1 ──| Step 3: 服务端发送 FIN
| | 服务端进入 LAST_ACK
| |
|──────── ACK, SEQ=u+1, ACK=w+1─→| Step 4: 客户端发送 ACK
| | 客户端进入 TIME_WAIT(2MSL)
| | 服务端进入 CLOSED四次挥手流程
| 步骤 | 报文 | 状态变化 |
|---|---|---|
| ① | 客户端 → 服务端:FIN=1, seq=u | 客户端不再发送数据,发出连接释放报文 |
| ② | 服务端 → 客户端:ACK=1, seq=v, ack=u+1 | 服务端确认收到 FIN,但可能还有数据要发送(半关闭状态) |
| ③ | 服务端 → 客户端:FIN=1, ACK=1, seq=w, ack=u+1 | 服务端数据发送完毕,发送 FIN 请求释放连接 |
| ④ | 客户端 → 服务端:ACK=1, seq=u+1, ack=w+1 | 客户端确认收到 FIN,进入 TIME_WAIT 状态(等待 2MSL) |
TIME_WAIT 状态(2MSL)
客户端在第四次挥手后进入 TIME_WAIT 状态,等待 2MSL(Maximum Segment Lifetime,最大报文段生存时间) 后自动关闭。
为什么要等待 2MSL?
- 确保最后的 ACK 到达服务端:如果 ACK 丢失,服务端会重发 FIN,客户端在 2MSL 内能收到并重发 ACK。
- 防止旧连接报文干扰新连接:2MSL 时间足够让本次连接的所有报文在网络中消失。
总结
| 层次能力 | UDP | TCP |
|---|---|---|
| 首部长度 | 8 字节(固定) | 20~60 字节(可变) |
| 连接管理 | ❌ 无连接 | ✅ 三次握手 + 四次挥手 |
| 可靠传输 | ❌ 不可靠 | ✅ 序号 + ACK + 重传 + 校验 |
| 流量控制 | ❌ 不支持 | ✅ 滑动窗口(rwnd) |
| 拥塞控制 | ❌ 不支持 | ✅ AIMD(慢开始/拥塞避免/快重传/快恢复) |
| 传输效率 | ⭐⭐⭐⭐ 高 | ⭐⭐ 中低 |
| 适用场景 | 实时通信、音视频、DNS、DHCP | 文件传输、网页浏览、邮件、远程登录 |
选择原则:
- 需要可靠传输、流量控制、拥塞控制 → 选择 TCP
- 需要低延迟、高效率、支持广播多播,可以容忍少量丢包 → 选择 UDP
下一步阅读:网络层 — 了解 IP 协议、路由选择与分组转发机制。
