深色模式
01 · 分层模型与一次请求的一生
这是网络模块的总纲。先看懂这篇的"封装-解封装"过程,后面四篇才有地方挂。
一句话本质
数据从上往下走,每层加一个头(封装);到了对方从下往上走,每层拆一个头(解封装)。网络的一切复杂度,都在这些头里。
生活类比:寄快递的层层包装
你写的信(应用层数据)
v 装进信封,写上"收件人、寄件人"(加 TCP 头)
v 装进快递袋,写上"地址、单号"(加 IP 头)
v 贴上面单,写上"本小区 3 号楼"(加 MAC 头)
v 交给快递员(物理传输)
到了分拣中心:
v 撕掉面单(拆 MAC 头)—— 因为要重新决定下一站
v 看快递袋上的地址(IP 头)—— 决定往哪发
v 贴上新面单(加新 MAC 头)—— 下一跳
到了收件人:
v 撕面单(拆 MAC)
v 撕快递袋(拆 IP)
v 拆信封(拆 TCP)
v 拿到信(应用层数据)关键:分拣中心(路由器)只拆到"快递袋"(IP 层),不会拆信封(TCP 层)。这是分层的精髓——每一层只关心自己那层的头。
核心机制
一、封装:从上往下,逐层加头
假设浏览器要发一个 HTTP 请求 GET /a:
应用层 GET /a HTTP/1.1 + Host: x.com
|
| 加 TCP 头:源端口、目的端口、序号、窗口
v
传输层 [TCP头][GET /a ...]
|
| 加 IP 头:源 IP、目的 IP、TTL
v
网络层 [IP头][TCP头][GET /a ...]
|
| 加 MAC 头:源 MAC、目的 MAC、校验
v
链路层 [MAC头][IP头][TCP头][GET /a ...][FCS]每个头解决的问题:
| 层 | 头里有什么 | 解决什么 |
|---|---|---|
| 链路层 | 源 MAC、目的 MAC | 这一跳交给谁 |
| 网络层 | 源 IP、目的 IP、TTL | 最终送到哪、能活多久(防环) |
| 传输层 | 源端口、目的端口、序号、确认号、窗口 | 交给哪个进程、保证不丢不乱 |
二、MTU 与 MSS:为什么要切
MTU(Maximum Transmission Unit)= 链路层能承载的最大帧载荷,以太网默认 1500 字节
MSS(Maximum Segment Size)= TCP 段的最大数据长度 = MTU - IP头(20) - TCP头(20) = 1460为什么要切:链路层一次传不了那么大的数据。你发 1MB 的数据,TCP 会切成约 700 个 MSS 大小的段。
切太大会怎样:如果 IP 包超过 MTU 且不允许分片,会被丢弃,返回 ICMP "需要分片"。这就是 PMTUD(路径 MTU 发现) 要解决的问题,也是某些网络"能 ping 通但打不开网页"的原因。
三、转发:每一跳发生了什么
主机 A --> 路由器 1 --> 路由器 2 --> 主机 B在主机 A:
- 查路由表:目的 IP 不在本网段 > 交给默认网关(路由器 1)。
- 查 ARP:网关 IP 对应的 MAC 是多少。
- 封装:目的 MAC = 路由器 1 的 MAC,目的 IP = 主机 B 的 IP。
在路由器 1:
- 拆链路层头(看目的 MAC 是自己,收下)。
- 看 IP 头里的目的 IP,TTL 减 1,查路由表决定下一跳。
- 重新封装:目的 MAC = 路由器 2 的 MAC,源 MAC = 路由器 1 出接口的 MAC,IP 头不变。
必记结论:
- MAC 每跳都变,IP 端到端不变(NAT 场景例外)。
- TTL 每跳减 1,减到 0 就丢弃并回 ICMP 超时——这是
traceroute的原理。
四、分片与重组
IP 层如果遇到超过 MTU 的包,可以分片(IPv4)。但分片很糟:
- 任一分片丢失,整个包要重传。
- 分片增加路由器负担。
所以现代做法是:IP 层不分片(设 DF 位),由 TCP 按 MSS 切好。IPv6 干脆取消了路由器分片。
五、端口:数据交给哪个进程
一个 TCP 连接由四元组唯一标识:
(源IP, 源端口, 目的IP, 目的端口)
所以:
同一个客户端可以同时开很多连接访问同一个服务器 —— 源端口不同
一个服务器端口(比如 80)可以同时服务成千上万个连接 —— 靠四元组区分这解释了一个常见疑问:为什么服务端只监听一个 80 端口,却能处理上万并发?因为连接不是靠端口区分的,是靠四元组区分的。
六、完整时序
① 浏览器 -> 本地 DNS 查询 www.example.com 【网络 05】
② 本地 DNS -> 浏览器 返回 IP 93.184.216.34
③ 浏览器 -> 服务器 SYN 【网络 02】
④ 服务器 -> 浏览器 SYN+ACK
⑤ 浏览器 -> 服务器 ACK => TCP 连接建立
⑥ 浏览器 -> 服务器 TLS 握手(若 HTTPS) 【网络 04】
⑦ 浏览器 -> 服务器 GET /index.html 【网络 04】
⑧ 服务器 -> 浏览器 200 OK + HTML
⑨ 双向 数据分片、编号、滑动窗口 【网络 03】
⑩ 浏览器 -> 服务器 FIN 【网络 02】
⑪ 服务器 -> 浏览器 ACK
⑫ 服务器 -> 浏览器 FIN
⑬ 浏览器 -> 服务器 ACK => 连接关闭为什么这么设计
反事实 1:如果不分层,会怎样
一个协议要同时管"找路 + 不丢包 + 数据格式 + 加密"。后果:
- 换 WiFi 就要重写整个协议栈。
- 想给 HTTP 加密(HTTPS),得改底层寻址逻辑。
- 每个应用(邮件、网页、视频)都要自己实现可靠传输。
分层让每一层可以独立演进:HTTP/2 只改了应用层,TCP 一点没动;QUIC 把可靠传输搬到 UDP 上,只动了传输层。
反事实 2:如果路由器要拆到应用层,会怎样
路由器要理解 HTTP、SMTP、FTP 每种协议的格式——不可能,而且每出一个新协议就要升级所有路由器。
所以路由器只拆到 IP 层:它只需要知道"目的 IP 是谁",不需要知道"里面装的是什么"。这就是"端到端原则":复杂的功能放在端上,网络中间尽量简单。
反事实 3:如果没有端口,会怎样
一台机器上跑着浏览器、微信、数据库。数据到了,交给谁?
没有端口的话,只能靠"应用自己识别数据"——每个应用都要读所有收到的包,判断"这是不是我的"。既低效又不安全。
端口本质是给进程编了个号,让内核能直接分发。
面试怎么问
Q:TCP/IP 四层(或 OSI 七层)分别是什么?各层有什么协议?
四层:应用层(HTTP/DNS/FTP)、传输层(TCP/UDP)、网络层(IP/ICMP/ARP 争议)、链路层(以太网/ARP)。 七层:物理、数据链路、网络、传输、会话、表示、应用。说完补一句"OSI 是教学模型,实际是 TCP/IP 四层",显得不背书。
Q:数据从应用层到物理层,经过了什么?
逐层封装,每层加头:TCP 头(端口、序号)> IP 头(IP、TTL)> MAC 头(MAC、FCS)。到对方逐层解封装,每层拆自己那个头,把剩下的往上交。
Q:路由器转发时,什么变了什么没变?
变了:源 MAC、目的 MAC(每跳重写)、TTL(每跳减 1)。 没变:源 IP、目的 IP(NAT 场景除外)、TCP 头(端口、序号全部不变)。 这是区分"懂不懂分层"的经典题。
Q:为什么服务端一个端口能处理上万连接?
因为连接由四元组标识(源IP、源端口、目的IP、目的端口),不是由端口标识。不同客户端的源 IP/端口不同,就是不同的连接。
追问链:
一次请求经过哪些层?
> 每层加了什么头?(端口 / IP / MAC)
> 路由器拆到哪一层?(只到 IP 层)
> 为什么不多拆?(端到端原则,中间要简单)
> MAC 每跳都变,IP 不变,为什么?(MAC 只管这一跳)
> 那 NAT 呢?(NAT 会改 IP,所以破坏了端到端,是过渡方案)和其他知识的连接
- < 来自 网络导读:两台机器怎么说话:这是模块总纲的展开
- < 来自 内核态与系统调用:用户程序怎么"申请"做事:封装解封装在内核协议栈里完成,
send/recv是入口 - > 影响 TCP 连接管理:三次握手、四次挥手、TIME_WAIT:TCP 头里的端口和序号,是后面所有机制的基础
- > 影响 TCP 可靠传输与拥塞控制:MSS 决定了切段大小,直接影响滑动窗口的效率
- > 影响 HTTP / HTTPS 与缓存:HTTP 是应用层数据,它不知道下面怎么传的
- > 影响 DNS 与 ARP:两个"翻译官":DNS 是应用层协议(自己也要走 UDP/TCP),ARP 是链路层的"翻译官"
自测 3 问
Q1:路由器转发时,为什么要重写 MAC 头?
点开看答案
因为 MAC 地址只在同一个局域网(广播域)内有效。
主机 A 和主机 B 可能隔了 10 个路由器,A 根本不知道 B 的 MAC(也不需要知道)。A 只知道"下一跳是网关",所以把目的 MAC 写成网关的。
网关收到后,要发给下一个网关,就得把目的 MAC 改成下一个网关的 MAC。每一跳都是"当前节点 > 下一个节点"的关系,所以 MAC 每跳都要重写。
而 IP 是端到端的最终地址,全程不变(NAT 除外)。
Q2:为什么服务端 80 端口能同时处理上万连接?
点开看答案
因为端口不是连接的唯一标识,四元组才是:
(客户端IP, 客户端端口, 服务器IP, 服务器端口)一万个客户端连过来,服务器 IP 和端口都是 1.2.3.4:80,但客户端 IP/端口各不相同,所以是 1 万个不同的连接。
内核的 socket 表按四元组查找,每个连接一个 socket 结构。"监听 80 端口"的那个 socket 只负责接受新连接(accept),接受后创建的新 socket 才承载数据。
Q3:TTL 是干什么的?为什么需要它?
点开看答案
TTL(Time To Live)是 IP 头里的一个计数器,每经过一个路由器减 1,减到 0 就丢弃并回一个 ICMP 超时。
存在理由:防止路由环路把网络打爆。如果路由表配错形成环,包会在两个路由器之间无限打转,每秒几百万个包会把链路彻底堵死。有了 TTL,最多转 64 跳就死掉。
副产品:traceroute 就是利用它——发 TTL=1 的包,第一个路由器回超时,就知道第一跳是谁;TTL=2 就知道第二跳,依次推出整条路径。
类比失效处 / 易错点
- "快递袋"类比会让人以为分拣中心要拆开看。实际路由器只看 IP 头,连 TCP 头都不看(除了 NAT 和防火墙)。
- "每层加头"不是无限的。头本身有开销:TCP+IP 头 40 字节,如果数据只有 1 字节,开销率 97.6%。所以小包合并(Nagle 算法)是有意义的。
- ARP 到底属于哪一层有争议。它工作在链路层和网络层之间,通常归为链路层,但它处理的是 IP 地址。
- "OSI 七层"不要和"TCP/IP 四层"混着说。面试时先答四层(实际),再提七层(模型)。
- IP 头不变,但 IP 包可能被分片。分片后每个分片有自己的 IP 头(部分字段复制),重组在目的主机完成。
✅ 验收清单
- 能画出封装/解封装图,标出每层加的头和头里的关键字段
- 能说出路由器转发时"什么变、什么不变"(MAC 变、IP 不变、TTL 减 1)
- 能解释为什么路由器只拆到 IP 层(端到端原则)
- 能用四元组解释"一个 80 端口为什么能扛上万连接"
- 能算出 MSS = MTU - 40,并说出为什么要切段
- 能解释 TTL 的两个作用(防环 + traceroute 原理)
- 合上书,用自己的话讲 3 分钟,中途不卡壳