TCP/IP 详解:理解互联网通信的基础
我们每天都在使用网络。
打开浏览器访问一个网站、使用 SSH 登录服务器、调用 HTTP API、连接 MySQL、使用 Redis,甚至程序之间建立 TCP 长连接,本质上都离不开一套共同的网络通信基础:
TCP/IP 协议族。
很多后端开发者知道 TCP、UDP、IP、端口这些概念,但如果把它们放在一起,经常会产生几个疑问:
TCP/IP 到底是什么?
TCP 和 IP 分别负责什么?
IP 地址和端口有什么区别?
TCP 为什么需要三次握手?
数据到底是如何从一台机器到另一台机器的?
Socket 又处于什么位置?
HTTP 和 TCP 又是什么关系?
理解这些问题之后,后面的 Socket、HTTP、HTTPS、WebSocket 才会真正容易理解。
本文不试图把计算机网络所有知识一次讲完,而是从后端开发最需要掌握的角度,建立一套完整的 TCP/IP 基础认知。
1. TCP/IP 到底是什么?
首先需要纠正一个常见认识:
TCP/IP 不是一个单独的协议,而是一组用于网络通信的协议族。
TCP/IP Protocol Suite,也就是 TCP/IP 协议族,包含多个不同层次、不同职责的协议。
例如:
应用层
├── HTTP
├── DNS
├── SMTP
└── SSH
传输层
├── TCP
└── UDP
网际层
├── IP
├── ICMP
└── ...
链路层
├── Ethernet
├── Wi-Fi
└── ...
这些协议共同完成网络通信。
IETF 的 RFC 1122 将 Internet 协议体系描述为分层结构,其中包括 Application Layer、Transport Layer、Internet Layer 和 Link Layer。RFC 1122 同时明确指出,严格的分层模型主要是一种组织和理解协议的方式,实际协议之间存在复杂的交互,并不意味着所有实现都必须机械地严格分层。
因此,理解 TCP/IP 最重要的不是死记“有几层”,而是理解:
每一层负责解决什么问题,以及这些协议如何协同完成一次通信。
2. TCP/IP 的协议分层
常见的 TCP/IP 模型可以抽象成四层:
┌────────────────────────────┐
│ 应用层 │
│ HTTP / DNS / SSH / SMTP │
├────────────────────────────┤
│ 传输层 │
│ TCP / UDP │
├────────────────────────────┤
│ 网际层 │
│ IP / ICMP │
├────────────────────────────┤
│ 链路层 │
│ Ethernet / Wi-Fi │
└────────────────────────────┘
不同教材可能会把链路层进一步拆成数据链路层和物理层,也可能采用五层模型。
而 OSI 模型则是七层:
OSI 七层:
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
因此不要简单认为:
TCP/IP 四层 = OSI 七层的简单合并
两者是不同的参考模型。
对于后端开发来说,更重要的是掌握 TCP/IP 各层的职责。
应用层
负责具体的应用协议。
例如:
HTTP
DNS
SSH
SMTP
WebSocket
这一层最接近我们编写的业务程序。
例如:
GET /users/1001 HTTP/1.1
Host: example.com
这就是应用层的数据。
传输层
负责端到端的进程通信。
最常见的是:
TCP
UDP
TCP 提供可靠、有序的字节流传输;UDP 提供无连接的数据报服务。
RFC 1122 将 TCP 描述为可靠的、面向连接的传输服务,而 UDP 是无连接的数据报传输服务。现代 TCP 的规范以 RFC 9293 为准。
网际层
主要负责:
IP 地址
数据包寻址
路由
最核心的协议就是:
IP
IP 解决的是:
数据应该送到哪台主机?
而不是:
数据一定能不能到?
IP 本身不提供 TCP 那样的端到端可靠传输保证。RFC 1122 明确说明,IP 是无连接的数据报服务,不保证数据报最终交付、顺序或不重复。
链路层
负责相邻网络节点之间的数据传输。
常见技术包括:
Ethernet
Wi-Fi
这一层更接近网卡、交换机和实际网络介质。
3. IP:数据应该送到哪台机器?
理解 TCP/IP,首先要理解 IP。
假设服务器地址:
192.168.1.100
客户端需要把数据发送给这台机器。
IP 的核心任务就是提供网络层面的寻址和转发。
可以简单理解:
客户端
│
│ IP 数据包
↓
路由器
│
↓
路由器
│
↓
服务器
192.168.1.100
中间可能经过多个路由器。
每一个路由器根据目标 IP 地址和路由表决定下一跳。
因此:
IP 主要解决的是“主机到主机”的网络寻址和数据包转发问题。
RFC 1122 对 IP 层的描述也包括选择下一跳以及处理收到的数据报等职责。
IPv4 和 IPv6
目前常见的两个 IP 版本是:
IPv4
IPv6
IPv4 地址是 32 位,例如:
192.168.1.100
IPv6 地址是 128 位,例如:
2001:db8::1
IPv6 的一个重要变化就是将地址空间从 IPv4 的 32 位扩展到了 128 位,同时对报头结构、扩展机制等进行了调整。
因此,IPv6 并不是“更大的 IPv4 地址”,而是 IP 协议的新版本。
4. TCP:如何可靠地传输数据?
IP 解决了:
数据发往哪台主机?
但它没有解决:
数据是否可靠地到达?
例如:
客户端
↓
IP 数据包
↓
网络
↓
服务器
网络中可能出现:
数据丢失
数据乱序
数据重复
网络拥塞
TCP 就是在 IP 之上提供可靠传输能力的协议。
RFC 9293 将 TCP 定义为一种面向连接的传输协议,并提供可靠、有序的字节流服务。TCP 使用序列号检测数据丢失,通过确认和重传机制处理可靠性问题,并通过端口号识别应用服务和复用不同的数据流。
可以简单理解为:
IP:
把数据包送过去
TCP:
尽可能保证数据正确、有序地交给应用程序
5. TCP 和 UDP 到底有什么区别?
TCP 和 UDP 都属于传输层。
但是设计目标不同。
| 对比 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 数据形式 | 字节流 | 数据报 |
| 可靠传输 | 提供 | 不提供 |
| 顺序保证 | 提供 | 不保证 |
| 重传 | 支持 | 不负责 |
| 流量控制 | 支持 | 不负责 |
| 拥塞控制 | 支持 | 不提供 TCP 意义上的机制 |
| 开销 | 相对更高 | 相对更低 |
| 典型应用 | HTTP/1.1、HTTPS、SSH | DNS、实时音视频等场景 |
这里需要特别注意:
UDP 并不是“不可靠所以速度一定更快”。
它只是没有像 TCP 那样在传输层提供可靠、有序的字节流服务,因此应用程序可以获得更直接的数据报通信能力,也可以自行决定是否需要可靠性、重传等机制。
RFC 1122 将 UDP 描述为一种最小化的传输服务,主要提供数据报传输、校验和以及基于端口的复用。
6. IP 地址和端口有什么区别?
这是后端开发中非常重要的一个概念。
假设一台服务器:
IP:
192.168.1.100
同时运行:
HTTP 80
HTTPS 443
SSH 22
MySQL 3306
Redis 6379
那么:
192.168.1.100
主要用于定位:
哪台主机?
而:
443
用于进一步定位:
这台主机上的哪个网络服务?
所以可以粗略理解为:
IP → 找到主机
Port → 找到主机上的服务/通信端点
TCP 使用源端口和目标端口进行应用服务复用。RFC 9293 的 TCP 规范也明确规定了 TCP 端口字段及其用于识别应用服务和复用连接的作用。
例如:
客户端
192.168.1.10:53021
│
│ TCP
↓
服务器
192.168.1.100:443
这里:
192.168.1.10
是客户端 IP。
53021
是客户端源端口。
192.168.1.100
是服务器 IP。
443
是服务器目标端口。
这四个信息共同参与确定一条 TCP 通信。
7. 一次 TCP 通信到底发生了什么?
假设浏览器访问:
https://example.com
从网络层面看,可以简化为:
浏览器
│
│ DNS
↓
获得服务器 IP
│
│ TCP
↓
建立连接
│
│ TLS
↓
建立安全连接
│
│ HTTP
↓
发送请求
│
↓
服务器处理
│
↓
HTTP 响应
这里其实已经涉及了多个协议。
从 TCP/IP 的角度,可以进一步理解为:
HTTP
↓
TCP
↓
IP
↓
Ethernet / Wi-Fi
发送数据时,上层数据会逐层封装。
例如 HTTP 请求:
HTTP Request
↓
TCP Segment
↓
IP Packet
↓
Ethernet Frame
可以抽象成:
┌──────────────────────────────────────┐
│ Ethernet Header │
│ ┌──────────────────────────────┐ │
│ │ IP Header │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ TCP Header │ │ │
│ │ │ ┌──────────────┐ │ │ │
│ │ │ │ HTTP Data │ │ │ │
│ │ │ └──────────────┘ │ │ │
│ │ └──────────────────────┘ │ │
│ └──────────────────────────────┘ │
└──────────────────────────────────────┘
这就是网络通信中非常重要的:
封装(Encapsulation)。
RFC 1122 对协议层之间的数据封装有明确描述:TCP segment 会被封装到 IP datagram 中,而 IP datagram 再交给链路层进行传输。
接收端则反过来:
Ethernet Frame
↓
IP Packet
↓
TCP Segment
↓
HTTP Data
↓
应用程序
这就是:
解封装(Decapsulation)。
8. TCP 三次握手解决什么问题?
TCP 是面向连接的协议。
在真正传输应用数据之前,需要建立 TCP 连接。
最经典的过程就是三次握手:
客户端 服务器
SYN ---------------------------->
<------------------------- SYN + ACK
ACK ---------------------------->
连接建立
可以简单理解:
第一次:
客户端 → 服务器
SYN
表示:
我想建立 TCP 连接。
第二次:
服务器 → 客户端
SYN + ACK
表示:
我收到了你的请求,同时我也希望建立连接。
第三次:
客户端 → 服务器
ACK
表示:
我收到你的响应。
双方完成必要的连接状态同步后,就可以进入数据传输阶段。
不过需要注意:
三次握手不是简单的“客户端说你好、服务器说你好、客户端说收到”。
TCP 握手涉及序列号、确认号以及连接状态的建立。RFC 9293 对 TCP 连接建立过程以及 SYN/ACK 等控制信息进行了规范。
关于三次握手的详细状态机、序列号以及 SYN Flood 等问题,可以在后续文章中单独展开。
9. TCP 为什么是“字节流”?
这是理解 Socket 时非常重要的一点。
TCP 给应用程序提供的是:
可靠、有序的字节流。
例如应用程序发送:
Hello
World
TCP 并不保证接收端一定按照:
Hello
World
两次 read() 就分别读到。
它可能表现为:
HelloWorld
也可能:
Hel
loWor
ld
甚至一次读取:
HelloWorld
也可能分多次读取。
因为 TCP 关注的是:
字节序列
而不是:
消息
这也是为什么 TCP 存在著名的:
粘包 / 拆包问题。
实际上,“粘包”这个说法容易让人误以为 TCP 在传输层定义了一个个业务消息,然后把消息粘到了一起。
更准确的说法是:
TCP 本身没有应用层消息边界。
如果应用程序需要消息边界,就必须自己设计协议,例如:
固定长度
长度字段 + Payload
特殊分隔符
TLV
JSON + 长度前缀
Protobuf
这也是下一篇 Socket 文章非常重要的内容。
10. TCP/IP、Socket、HTTP 到底是什么关系?
把前面的内容放在一起,就很清晰了。
应用程序
│
HTTP / WebSocket
│
Socket
│
TCP / UDP
│
IP
│
Ethernet / Wi-Fi
│
网络
这里的 Socket 并不是一个网络协议。
它更准确地说是:
操作系统向应用程序提供的网络通信接口。
应用程序通常不会直接操作 TCP 报文,而是通过 Socket API 使用 TCP 或 UDP。
例如一个 TCP 服务端通常会经历:
socket()
↓
bind()
↓
listen()
↓
accept()
↓
read() / write()
↓
close()
客户端则通常是:
socket()
↓
connect()
↓
read() / write()
↓
close()
因此可以建立这样一个关系:
HTTP
↓
使用 TCP
↓
操作系统提供 Socket
↓
TCP/IP 协议栈
↓
网卡
↓
网络
下一篇文章专门讨论 Socket 时,就可以在这个基础上继续深入。
11. TCP/IP 对后端开发有什么意义?
理解 TCP/IP 并不是为了考试。
很多后端问题,最后都会落到网络层面。
例如:
HTTP 请求为什么超时?
可能涉及:
DNS
TCP 建连
网络延迟
TCP 重传
服务端处理
连接池
HTTP Keep-Alive
为什么服务端出现大量 TIME_WAIT?
需要理解:
TCP 连接生命周期
主动关闭连接的一方
四次挥手
TIME_WAIT
为什么 Socket 读取不到完整消息?
需要理解:
TCP 是字节流
没有消息边界
为什么 WebSocket 需要心跳?
需要理解:
TCP 连接 ≠ 永远存活
网络设备可能丢弃空闲连接
TCP 本身也不等价于应用层存活检测
RFC 9293 也明确指出,TCP 是面向连接的,但 TCP 本身并不天然提供应用层意义上的 liveness detection(存活检测)能力。
为什么高并发服务需要 Epoll?
这就需要进一步理解:
Socket
↓
阻塞 / 非阻塞 IO
↓
IO 多路复用
↓
Epoll
↓
Reactor
这些内容都会建立在 TCP/IP 和 Socket 的基础之上。
12. 总结
TCP/IP 最重要的不是记住各种协议名称,而是理解它们各自解决什么问题。
可以用一句话概括:
IP:
解决数据包应该送到哪台主机。
TCP:
解决应用之间如何可靠、有序地传输字节流。
UDP:
提供简单的无连接数据报传输。
Port:
帮助传输层定位主机上的网络服务。
Socket:
为应用程序提供网络通信接口。
HTTP:
定义 Web 应用之间如何交换请求和响应。
把这些关系串起来:
应用程序
│
HTTP / WebSocket
│
Socket
│
┌──────┴──────┐
│ │
TCP UDP
│ │
└──────┬──────┘
↓
IP
↓
Ethernet / Wi-Fi
↓
网络
这也是理解后续网络协议最重要的一张图。
TCP/IP 解决的是网络通信基础问题,而 Socket 则是应用程序实际使用 TCP/UDP 进行网络通信的重要接口。
另一篇:
参考资料
RFC 1122 — Requirements for Internet Hosts - Communication Layers RFC 1122 官方文档
RFC 9293 — Transmission Control Protocol (TCP) 当前 TCP 的 Internet Standards Track 核心规范,已取代 RFC 793 中的 TCP 规范部分。 RFC 9293 官方文档
RFC 8200 — Internet Protocol, Version 6 (IPv6) Specification IPv6 的核心规范。 RFC 8200 官方文档