4595 字
23 分钟
网络:传输层

如果说网际层解决的是“数据要发到哪台主机”,那么传输层进一步解决的是“数据应该交给主机上的哪个程序,以及多个主机之间如何进行可靠的数据传输”。

TCP/IP 四层模型中的传输层主要包括 TCP、UDP、端口、Socket、可靠传输、流量控制、拥塞控制以及连接管理 等概念。理解这一层之后,才能继续理解 HTTP、DNS、SSH 等应用层协议为什么能够同时运行在同一台主机上。

传输层是什么#

TCP/IP 四层模型:

┌────────────────────┐
│ 应用层 │
├────────────────────┤
│ 传输层 │
├────────────────────┤
│ 网际层 │
├────────────────────┤
│ 网络接口层 │
└────────────────────┘

理解传输层时,先区分相邻层的职责:

网络接口层
↓
Ethernet / MAC / Frame / 网卡
网际层
↓
IP / IP 地址 / 子网 / 路由 / ICMP / ARP

传输层位于它们之上。

它主要负责:

主机
↓
进程之间的通信

也就是说:

IP 地址定位主机,端口定位主机上的服务或通信端点。

例如:

192.168.1.10:80

可以拆成:

192.168.1.10
↓
目标主机
80
↓
目标端口

因此:

IP
↓
找到哪台主机
Port
↓
找到主机上的哪个服务

为什么需要传输层#

假设一台服务器同时运行:

Web Server
SSH Server
DNS Server
Database

它们都使用同一块网卡和同一个 IP 地址。

例如:

服务器
IP = 192.168.1.10

但客户端需要区分:

Web
SSH
DNS
Database

这时候就需要:

Port(端口)

可以理解为:

192.168.1.10
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
:22 :53 :80
│ │ │
▼ ▼ ▼
SSH DNS HTTP

因此:

IP + Port

共同构成了网络通信中的一个重要寻址概念。


端口#

什么是 Port#

TCP 和 UDP 都使用:

16 bit 端口号

因此端口范围是:

0
~
65535

端口号本身只是一个数字。

真正的含义取决于:

传输协议
+
具体应用

例如:

TCP 22
TCP 80
TCP 443
UDP 53

并不意味着:

80 永远只能用于 HTTP

而是:

某个应用协议通常会约定使用某个端口。


端口范围#

传统上可以把端口大致理解为:

0 ~ 1023
↓
知名端口
1024 ~ 49151
↓
注册端口
49152 ~ 65535
↓
动态 / 私有端口

其中实际系统、IANA 注册以及具体操作系统分配策略可能存在差异。

IANA 维护官方的 Service Name and Transport Protocol Port Number Registry。


源端口与目标端口#

一次 TCP / UDP 通信通常存在:

Source Port
Destination Port

例如客户端访问服务器:

Client
192.168.1.10:50000
│
│
▼
Server
192.168.1.20:443

可以理解为:

源 IP = 192.168.1.10
源端口 = 50000
目标 IP = 192.168.1.20
目标端口 = 443

于是一个方向上的通信可以表示为:

192.168.1.10:50000
↓
192.168.1.20:443

返回方向则相反:

192.168.1.20:443
↓
192.168.1.10:50000

TCP 与 UDP#

传输层最重要的两个协议:

TCP
UDP

它们都属于传输层,但设计目标不同。

可以先概括为:

TCP
↓
面向连接
可靠
有序
字节流
UDP
↓
无连接
尽力交付
数据报
开销较小

注意:

“UDP 不可靠”并不是说 UDP 一定会丢包,而是 UDP 协议本身不提供类似 TCP 的可靠传输、排序和重传机制。


UDP#

UDP 是什么#

UDP(User Datagram Protocol)是一种无连接的传输层协议。

RFC 768 定义了 UDP。

其特点可以概括为:

简单
无连接
数据报
开销低

UDP 不负责建立一个类似 TCP 那样的连接状态。


UDP Datagram#

UDP 传输的数据单位称为:

UDP Datagram

可以理解为:

Application Data
│
▼
UDP Datagram
│
▼
IP Packet

UDP 首部很简单:

┌──────────────────┬──────────────────┐
│ Source Port │ Destination Port │
├──────────────────┼──────────────────┤
│ Length │ Checksum │
├──────────────────┴──────────────────┤
│ Payload │
└─────────────────────────────────────┘

主要包含:

源端口
目标端口
长度
校验和

UDP 的特点#

UDP 不提供 TCP 那样的:

连接建立
可靠重传
顺序保证
流量控制
拥塞控制

因此它更适合某些强调:

低延迟
简单通信
实时性
应用自行控制可靠性

的场景。

常见应用包括:

DNS
DHCP
实时音视频
部分游戏通信
QUIC 的底层传输

不过具体协议是否使用 UDP 仍然由协议设计决定。


TCP#

TCP 是什么#

TCP(Transmission Control Protocol)是一种:

面向连接的、可靠的、字节流传输协议。

RFC 9293 是当前 TCP 的主要规范之一。

TCP 需要维护通信双方的状态。

可以简单理解为:

Client
│
│ 建立连接
▼
Server
│
│
▼
TCP Connection

TCP Segment#

TCP 传输的数据单位通常称:

TCP Segment

可以理解为:

Application Data
│
▼
TCP Segment
│
▼
IP Packet

TCP 首部比 UDP 复杂得多。

简化表示:

┌─────────────────┬─────────────────┐
│ Source Port │ Dest Port │
├─────────────────┼─────────────────┤
│ Sequence Number │
├───────────────────────────────────┤
│ Acknowledgment Number │
├───────┬───────┬───────────────────┤
│ Flags │ Window│ ... │
├───────┴───────┴───────────────────┤
│ Checksum │
├───────────────────────────────────┤
│ Urgent Pointer / Options ... │
├───────────────────────────────────┤
│ Payload │
└───────────────────────────────────┘

其中非常重要的字段包括:

Sequence Number
Acknowledgment Number
Flags
Window
Checksum

TCP 三次握手#

为什么要握手#

TCP 是面向连接的,因此通信双方需要首先建立连接状态。

典型过程是:

Client Server
│ │
│ -------- SYN ---------------> │
│ │
│ <------ SYN + ACK ------------ │
│ │
│ -------- ACK ---------------> │
│ │
│ Established │

这就是:

TCP Three-Way Handshake


第一次:SYN#

客户端发送:

SYN

表示:

我想建立 TCP 连接。

其中会携带客户端选择的初始序列号等信息。

Client
│
│ SYN
▼
Server

第二次:SYN + ACK#

服务器收到 SYN 后:

Server
│
│ SYN + ACK
▼
Client

表示:

我收到了你的请求
+
我也愿意建立连接

第三次:ACK#

客户端收到服务器响应后:

Client
│
│ ACK
▼
Server

双方就可以进入:

Established

状态。


三次握手到底解决什么#

不能简单说:

“三次握手就是为了确认双方都在线。”

它更准确的作用包括:

同步双方的初始序列号
确认双向通信能力
建立双方 TCP 状态

因此:

SYN
↓
建立初始状态
SYN + ACK
↓
服务器确认并建立自己的状态
ACK
↓
客户端确认服务器响应

TCP 四次挥手#

为什么关闭连接需要四步#

TCP 是全双工通信。

也就是说:

A → B
B → A

两个方向可以独立关闭。

因此关闭连接通常涉及:

FIN
ACK
FIN
ACK

典型流程:

Client Server
│ │
│ -------- FIN ---------------> │
│ <-------- ACK --------------- │
│ │
│ <-------- FIN --------------- │
│ -------- ACK ---------------> │
│ │
│ Closed │

因此:

TCP 的连接关闭通常被称为“四次挥手”。

但实际抓包中具体报文可能因为实现和时序有所不同,例如 ACK 可能与其他报文合并,因此不要把“四次”理解成绝对固定的报文数量。


TCP 序列号与确认号#

TCP 的可靠传输非常依赖:

Sequence Number
Acknowledgment Number

例如:

发送方
Segment 1
Seq = 1000
Length = 500

那么接收方如果完整收到:

1000 ~ 1499

通常会确认下一个希望收到的位置:

ACK = 1500

因此可以理解为:

Seq
↓
“这一段数据从哪里开始”
ACK
↓
“我已经收到哪里,并希望下一个从哪里开始”

为什么需要序列号#

因为网络中的数据包可能:

乱序
丢失
重复
延迟

例如发送:

Segment A
Segment B
Segment C

网络中可能出现:

A
C
B

TCP 可以利用序列号判断:

数据顺序
数据范围
重复数据
缺失数据

从而实现有序的字节流交付。


TCP 重传#

假设:

发送:
A
B
C

但:

B

在网络中丢失。

接收端可能持续确认:

ACK

表明自己还缺少某个位置的数据。

发送端检测到丢失后,就可能重新发送对应数据。

可以简化为:

A ─────────────►
B ─────X
C ─────────────►
收到情况:
A
缺 B
C
↓
重新发送 B
↓
B ─────────────►

这就是 TCP 可靠传输的重要基础。


TCP 滑动窗口#

如果发送方:

发送一个
等待 ACK
发送一个
等待 ACK

效率会非常低。

因此 TCP 使用窗口机制允许:

在等待确认之前连续发送多个字节的数据。

例如:

发送窗口
┌────┬────┬────┬────┬────┐
│ A │ B │ C │ D │ E │
└────┴────┴────┴────┴────┘

可以同时存在多个尚未确认的数据。

收到确认后:

┌────┬────┬────┬────┬────┐
│ A │ B │ C │ D │ E │
└────┴────┴────┴────┴────┘
↑
ACK

窗口向前滑动:

┌────┬────┬────┬────┬────┐
│ B │ C │ D │ E │ F │
└────┴────┴────┴────┴────┘

因此称为:

Sliding Window(滑动窗口)


TCP 流量控制#

为什么需要流量控制#

假设:

发送方很快
接收方很慢

如果发送方无限制地发送:

发送发送发送发送……

接收方缓冲区最终可能被填满。

因此接收方需要告诉发送方:

我现在还能接收多少数据。

TCP 使用:

Receive Window(接收窗口)

进行流量控制。


接收窗口#

可以简单理解:

Receiver
│
│ 告诉 Sender:
│ 我还能接收 N 字节
▼
Sender
│
│ 控制发送量
▼
Receiver

于是:

发送速度
↓
受到接收方处理能力限制

这就是:

Flow Control

核心解决:

发送方
vs
接收方

速度不匹配的问题。


TCP 拥塞控制#

流量控制解决的是:

发送方 ↔ 接收方

而拥塞控制关注的是:

发送方
↓
网络
↓
接收方

也就是:

网络本身是否拥堵。


为什么需要拥塞控制#

假设:

主机 A
↓
路由器
↓
路由器
↓
主机 B

如果大量发送方同时高速发送:

A ─┐
B ─┼──► Network
C ─┘

中间网络设备可能出现:

队列堆积
丢包
延迟增加

TCP 因此需要动态调整发送速率。


拥塞窗口#

TCP 通过:

Congestion Window(拥塞窗口,cwnd)

控制在网络中可以同时维持多少未确认数据。

最终发送端的有效发送窗口通常会受到:

接收窗口 rwnd

和:

拥塞窗口 cwnd

共同限制。

可以简化理解为:

实际可发送范围
≈
min(rwnd, cwnd)

流量控制与拥塞控制的区别#

这是 TCP 中非常重要的一组概念。

Flow Control
↓
关注接收方
Congestion Control
↓
关注网络

可以画成:

Sender
│
│
▼
Network
│
│
▼
Receiver
↑
│
流量控制
关注 Receiver 能不能接住
拥塞控制
关注 Network 能不能承受

因此:

接收方太慢
↓
流量控制
网络太拥堵
↓
拥塞控制

TCP 的可靠传输机制#

把前面的概念放到一起,可以理解 TCP 的可靠性来自多个机制共同作用:

TCP
│
├── Sequence Number
├── Acknowledgment
├── Retransmission
├── Sliding Window
├── Flow Control
├── Congestion Control
└── Connection Management

也就是说:

TCP 的可靠性不是由某一个字段提供,而是一整套机制共同实现的。


UDP 与 TCP 的区别#

可以从整体上比较:

特性TCPUDP
连接面向连接无连接
数据形式字节流数据报
可靠传输提供不提供
顺序保证提供不提供
重传提供不提供
流量控制提供不提供
拥塞控制提供不提供
首部相对复杂简单
通信开销相对较高相对较低
典型场景HTTP、SSH 等DNS、DHCP、实时通信等

这里的:

TCP 更可靠
UDP 更简单

并不意味着:

TCP 一定更快
UDP 一定更快

具体性能取决于:

网络条件
数据规模
应用协议
延迟要求
丢包率
实现方式

Socket#

什么是 Socket#

应用程序要使用 TCP / UDP 通信,需要操作系统提供编程接口。

其中最重要的抽象之一就是:

Socket

可以简单理解为:

Application
│
▼
Socket
│
▼
TCP / UDP
│
▼
IP

应用程序不需要直接操作:

Ethernet Frame
MAC
网卡

而是通常通过 Socket API 与传输层通信。


Socket 地址#

一个 TCP 通信端点可以抽象成:

IP + Port + Protocol

例如:

TCP
192.168.1.10:443

或:

UDP
192.168.1.10:53

因此:

192.168.1.10:443/TCP

和:

192.168.1.10:443/UDP

是不同的通信端点。


TCP 连接如何唯一确定#

一个 TCP 连接通常由:

源 IP
源端口
目标 IP
目标端口
协议

这些信息共同确定。

也常称为:

Four-Tuple(四元组)

例如:

192.168.1.10:50000
↓
192.168.1.20:443

对应:

Source IP = 192.168.1.10
Source Port = 50000
Destination IP = 192.168.1.20
Destination Port = 443
Protocol = TCP

因此同一台服务器:

192.168.1.20:443

可以同时与大量客户端建立 TCP 连接:

Client A :50000 ──► Server :443
Client B :50001 ──► Server :443
Client C :50002 ──► Server :443

因为每条连接的四元组不同。


服务器为什么可以同时服务很多客户端#

假设服务器:

192.168.1.20:443

客户端:

A:50000
B:50001
C:50002

它们分别建立:

A:50000 → 192.168.1.20:443
B:50001 → 192.168.1.20:443
C:50002 → 192.168.1.20:443

虽然:

目标 IP
目标端口

完全一样,但:

源 IP
源端口

不同。

因此操作系统可以区分这些连接。

可以理解为:

Server
192.168.1.20
│
:443
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
Client A Client B Client C
:50000 :50001 :50002

这就是服务器能够同时接受大量连接的基础之一。


TCP 状态#

TCP 是有状态协议。

一个连接在生命周期中会经历不同状态,例如:

LISTEN
SYN-SENT
SYN-RECEIVED
ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT
CLOSING
LAST-ACK
TIME-WAIT
CLOSED

最重要的可以先掌握:

LISTEN
↓
等待连接
SYN-SENT / SYN-RECEIVED
↓
建立连接
ESTABLISHED
↓
正常通信
FIN-WAIT / CLOSE-WAIT 等
↓
连接关闭过程
TIME-WAIT
↓
关闭后的特定状态

可以使用:

Terminal window
ss -tan

查看 TCP 连接状态。


LISTEN 是什么#

服务器程序启动 TCP 服务后,通常会:

创建 Socket
↓
绑定 IP / Port
↓
进入 LISTEN
↓
等待客户端连接

可以简单表示:

Application
│
▼
Socket
│
▼
LISTEN
│
▼
等待 SYN

例如:

0.0.0.0:80

表示某个程序正在监听 TCP 80 端口,并等待连接。


ESTABLISHED#

建立连接之后:

Client
│
▼
Server

双方进入:

ESTABLISHED

表示 TCP 连接已经建立,可以进行正常数据传输。

例如:

Terminal window
ss -tan

可能看到:

ESTAB

这就是:

Established

的缩写。


TIME_WAIT#

TCP 连接关闭后,主动关闭的一方可能进入:

TIME_WAIT

这并不是:

“程序还在运行”。

它属于 TCP 连接管理机制的一部分。

其重要目的之一是:

确保网络中旧的延迟报文不会干扰后续新的连接

并确保必要的 ACK 重传机制能够正常工作。

因此:

TIME_WAIT

本身并不等于故障。

在高并发服务器中,如果大量连接同时关闭,可能看到大量:

TIME_WAIT

这时应该结合实际连接模式和系统资源进行分析,而不是看到它就认为:

“TCP 出问题了”。


TCP 与应用层#

现在可以把 TCP 放回整个协议栈:

应用层
│
├── HTTP
├── SSH
├── DNS
└── ...
│
▼
传输层
│
├── TCP
└── UDP
│
▼
网际层
│
├── IPv4
└── IPv6
│
▼
网络接口层
│
└── Ethernet

例如访问:

https://example.com

可以粗略理解为:

HTTP
↓
TCP
↓
IP
↓
Ethernet

每一层负责不同的问题。


一次 TCP 通信的完整过程#

假设:

客户端
192.168.1.10
服务器
192.168.1.20:80

客户端访问服务器。

完整流程可以简化成:

Application
│
│ HTTP
▼
TCP
│
Three-Way
Handshake
│
▼
TCP Connection
│
▼
IP Packet
│
▼
Ethernet Frame
│
▼
网络
│
▼
服务器

如果建立连接:

SYN
↓
SYN + ACK
↓
ACK
↓
Established

然后开始传输:

Application Data
↓
TCP Segment
↓
IP Packet
↓
Ethernet Frame

服务器收到后:

Ethernet
↓
IP
↓
TCP
↓
Port 80
↓
HTTP Server

这样一个 HTTP 请求最终才能到达:

具体的服务器进程

UDP 通信#

UDP 会简单很多。

例如:

Client
192.168.1.10:50000
Server
192.168.1.20:53

客户端发送 DNS 查询。

可以理解为:

Application Data
│
▼
UDP Datagram
│
▼
IP Packet
│
▼
Ethernet Frame
│
▼
Network
│
▼
Server :53

不需要:

TCP Three-Way Handshake

也没有:

TCP Connection State

这种连接管理机制。


传输层的整体认知模型#

现在可以把这一层浓缩成:

传输层
│
┌────────────┴────────────┐
│ │
▼ ▼
TCP UDP
│ │
┌──────┼──────┐ │
│ │ │ │
▼ ▼ ▼ ▼
连接 可靠性 拥塞控制 数据报
│ │ │ │
│ │ ├── Flow Control │
│ │ └── Congestion │
│ │ │
▼ ▼ ▼
Sequence ACK Port
Number Retransmission │
│ │ │
└──────┴──────────┬──────────────┘
▼
Socket
│
▼
IP Layer

可以进一步浓缩成:

IP
↓
哪台主机
Port
↓
哪个服务 / 通信端点
TCP
↓
可靠的字节流通信
UDP
↓
简单的数据报通信

而 TCP 的核心机制:

连接
↓
序列号
↓
确认
↓
重传
↓
滑动窗口
↓
流量控制
↓
拥塞控制
↓
连接关闭

共同构成了 TCP 的可靠传输体系。


常见传输层排障思路#

当出现:

“网络通,但是服务访问不了”

不能只检查:

ping

因为:

ping
↓
主要验证 IP 层连通性

而服务访问还需要检查:

TCP / UDP
+
Port
+
Application

可以形成这样的排障层次:

应用层
↓
服务是否正常?
传输层
↓
端口是否监听?
连接是否建立?
网际层
↓
IP 是否可达?
路由是否正确?
网络接口层
↓
网卡 / 链路是否正常?

例如:

Terminal window
ss -lnt

可以查看 TCP 监听端口。

Terminal window
ss -nt

可以查看 TCP 连接。

Terminal window
ss -lun

可以查看 UDP Socket。

这比单纯执行:

Terminal window
ping server

能提供更具体的信息。


TCP/IP 四层模型中的传输层#

到这里,可以把四层模型完整串起来:

┌──────────────────────────────┐
│ 应用层 │
│ HTTP / DNS / SSH / ... │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ 传输层 │
│ TCP / UDP │
│ Port / Socket │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ 网际层 │
│ IPv4 / IPv6 / Routing │
│ ICMP / ARP │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ 网络接口层 │
│ Ethernet / MAC / Frame / NIC │
└──────────────────────────────┘

可以把每一层的问题分别概括成:

网络接口层
↓
怎么在当前链路上传输?
网际层
↓
数据应该到哪个 IP?
传输层
↓
应该交给哪个端口?
如何传输?
应用层
↓
具体业务数据是什么?

因此:

传输层是连接“网络”和“应用”的关键一层。

它把:

主机之间的 IP 通信

进一步变成:

进程之间的网络通信

同时提供:

TCP
↓
可靠、有序、面向连接的字节流
UDP
↓
简单、无连接的数据报

这就是 TCP/IP 四层模型中传输层最核心的内容。

外部参考#

网络:传输层
https://tamakara.top/posts/学习笔记/网络传输层/
作者
魂辛カラ
发布于
2026-09-13
许可协议
CC BY-NC-SA 4.0