OSI 七层与 TCP/IP 四层
一句话:分层不是让你背的,是让你出问题时知道该去哪儿看。
阅读路径:先看两张模型(二、四)→ 再看一个包怎么走(五、六)→ 最后看怎么用它排错(七)。
一、先搞懂"分层"到底在分什么
把数据从 A 送到 B,要做很多事:找地址、保证不丢、加密、找应用……如果全塞给一个程序做,根本没法维护。
所以拆成流水线,每一层只干一件事,只关心自己的头:
应用层 → "这是什么业务" (HTTP/FTP/DNS)
传输层 → "交给哪个进程" (端口)
网络层 → "送到哪台机器" (IP)
链路层 → "下一跳是谁" (MAC)
物理层 → "怎么变成电信号" (网线/光纤)
核心思想:每一层只加自己的头,不关心别人加了什么。 这就是"信封套信封"。
二、OSI 七层(理论模型)
| 层 | 名称 | 一句话职责 | 典型协议 | 设备 |
|---|---|---|---|---|
| 7 | 应用层 | 给用户/程序提供接口 | HTTP、FTP、DNS、SMTP、SSH | — |
| 6 | 表示层 | 编码、压缩、加密 | TLS/SSL、JPEG、ASCII | — |
| 5 | 会话层 | 建立/管理/终止会话 | RPC、NetBIOS | — |
| 4 | 传输层 | 进程到进程通信 | TCP、UDP | — |
| 3 | 网络层 | 主机到主机寻址与路由 | IP、ICMP、IGMP | 路由器、三层交换机 |
| 2 | 数据链路层 | 帧、MAC 寻址 | Ethernet、ARP、VLAN | 交换机、网桥 |
| 1 | 物理层 | 比特流传输 | 电信号/光信号 | 网线、光纤、网卡 |
记忆口诀(自下往上):物、链、网、传、会、表、应。
三、TCP/IP 四层(实际模型)
3.1 应用层
对应 OSI 的应用层 + 表示层 + 会话层(三合一),为用户提供所需要的各种服务。
例如:FTP、Telnet、DNS、SMTP。
为什么三合一? 因为在实际实现里,编码、加密、会话管理都是应用自己处理的——浏览器自己管 Cookie 和会话,自己调 OpenSSL 做加密。OSI 把它们拆成三层,理论上很漂亮,但实践中没人这么实现。
3.2 传输层
对应 OSI 的传输层,为应用层提供端到端(进程到进程)的服务,保证数据包的顺序传送以及数据的完整性。
该层定义了两个主要协议:TCP(传输控制协议) 和 UDP(用户数据报协议)。
这一层最关键的是"端口"——它是应用层与传输层的接口:
IP 地址 → 哪台机器(大楼地址)
端口 → 哪个应用(房间号)
- 往上:应用
bind()占住 80 端口,说"80 的数据给我" - 往下:传输层看目的端口 80,把数据交给 nginx
同一台机器靠端口区分不同服务——这就是为什么 Web、SSH、MySQL 能同时跑在一台机上。
为什么叫"进程到进程",为什么是 TCP / UDP
一台服务器上同时跑着三个服务:
192.168.1.10
├── nginx → 监听 80
├── sshd → 监听 22
└── mysql → 监听 3306
一个包到达时,IP 头里只有"目的 IP",最多只能判断"这是给我这台机器的",没法判断"给哪个进程"。补上这一环的就是端口。
三种地址,对应三个层级:
| 层 | 地址 | 标识的是 |
|---|---|---|
| 数据链路层 | MAC 地址 | 哪块网卡(下一跳) |
| 网络层 | IP 地址 | 哪台机器 |
| 传输层 | 端口号 | 哪个进程 |
所以"进程到进程"不是"必须由 TCP/UDP 来完成",而是这一层的职责是用端口把包交给正确的进程。TCP 和 UDP 只是承担这个职责的两个协议。
类比:"交通工具"不是"必须由汽车和火车组成",只是这两种最常见。
反例:ICMP 没有端口。
ping 走 ICMP,而 ICMP 头里根本没有端口字段——因为 ping 的回复由内核直接代答,不需要交给某个用户进程。
ICMP(ping): 跑在 IP 上,没有端口 ← 不需要区分进程
TCP / UDP: 跑在 IP 上,有端口 ← 要交给具体应用
这正好反过来证明:传输层的价值不在协议本身,而在"需要区分进程"这件事。
TCP 和 UDP 都解决"进程到进程",但服务级别不同:
| TCP | UDP | |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 保证不丢、不重、有序 | 不保证 |
| 传输方式 | 字节流 | 数据报(一次一个包) |
| 速度 | 慢一些 | 快 |
| 典型应用 | HTTP、SSH、MySQL、FTP | DNS、SNMP、视频流、游戏 |
一句话:TCP 是"打电话"(先接通、确认对方在听);UDP 是"寄明信片"(写好就扔出去)。
补充:传输层不只这两个,还有 SCTP、DCCP,以及 QUIC(HTTP/3 的底层,跑在 UDP 上)。说"定义了 TCP 和 UDP"指的是它们最主流。
3.3 网际互联层
对应 OSI 的网络层,主要解决主机到主机的通信问题。
该层有三个主要协议:IP(网际协议)、IGMP(互联网组管理协议)、ICMP(互联网控制报文协议)。
三个协议各干什么:
| 协议 | 干什么 |
|---|---|
| IP | 寻址 + 路由,把包从一台主机送到另一台 |
| ICMP | 报错和探测(ping、traceroute 都靠它) |
| IGMP | 组播成员管理(一般业务用不到) |
这一层怎么把包送到别的网段? 靠网关和路由表接力——详见第六节。
3.4 网络接口层
对应 OSI 的物理层和数据链路层,负责监视数据在主机和网络之间的交换。
地址解析协议(ARP,把 IP 解析成 MAC 地址)工作在此层,即 OSI 的数据链路层。
ARP 的位置有点特殊——它的职责是"用 IP 找 MAC",横跨网络层和链路层。教材一般归到链路层,但你在排障时要记住:ARP 不通,就等于这一跳走不过去。
四、两张模型的对照(这张表要背下来)
| OSI 七层 | TCP/IP 四层 | 对应关系 |
|---|---|---|
| 应用层 | 应用层 | ┐ |
| 表示层 | 应用层 | ├ 三合一 |
| 会话层 | 应用层 | ┘ |
| 传输层 | 传输层 | 一对一 |
| 网络层 | 网际互联层 | 一对一 |
| 数据链路层 | 网络接口层 | ┐ 二合一 |
| 物理层 | 网络接口层 | ┘ |
OSI 7 TCP/IP 4
应用 ┐
表示 ├──────→ 应用层 (3 合 1)
会话 ┘
传输 ───────→ 传输层
网络 ───────→ 网际互联层
链路 ┐
物理 ┘──────→ 网络接口层 (2 合 1)
验算:3 + 1 + 1 + 2 = 7 ✅
五、数据封装:一层加一个信封
这是理解整套模型的关键动作。发数据时从上往下"套信封",收数据时从下往上"拆信封"。
5.1 发送方:逐层加头
┌──────────────────────────────────────┐
│ 应用层:HTTP 报文 │
│ GET /index.html HTTP/1.1 │
└──────────────────────────────────────┘
↓ 加 TCP 头(源端口 54321、目的端口 443)
┌─────────┬────────────────────────────┐
│ TCP 头 │ HTTP 数据 │ ← 叫「段 segment」
└─────────┴────────────────────────────┘
↓ 加 IP 头(源 IP、目的 IP)
┌─────────┬─────────┬──────────────────┐
│ IP 头 │ TCP 头 │ HTTP 数据 │ ← 叫「包 packet」
└─────────┴─────────┴──────────────────┘
↓ 加帧头(源 MAC、目的 MAC)+ 帧尾(FCS 校验)
┌────────┬─────────┬─────────┬─────────┬──────┐
│ 帧头 │ IP 头 │ TCP 头 │ HTTP数据 │ FCS │ ← 叫「帧 frame」
└────────┴─────────┴─────────┴─────────┴──────┘
↓ 转成电信号/光信号
0101010101010101 ← 叫「比特 bit」
四种数据单元的叫法(面试爱问):
| 层 | 单位 | 英文 |
|---|---|---|
| 传输层 | 段 | segment |
| 网络层 | 包 | packet |
| 链路层 | 帧 | frame |
| 物理层 | 比特 | bit |
5.2 接收方:逐层拆头
物理层 收到电信号 → 还原成帧
链路层 拆帧头 → 检查 FCS,目标 MAC 是不是我?
网络层 拆 IP 头 → 目标 IP 是不是我?不是就转发
传输层 拆 TCP 头 → 目的端口 443 → 交给监听 443 的进程
应用层 拿到 HTTP 报文 → 处理
关键理解:每一层只拆自己那层头,不看别人的内容。
这也解释了为什么中间的路由器只看 IP 头就够——它不需要知道你在传 HTTP 还是 SSH。
5.3 一个必须记住的细节
IP 地址:端到端不变(源 IP 和目的 IP 从头到尾一样)
MAC 地址:每过一跳路由器就变(重写成下一跳的)
下一节就把这句话走一遍。
六、数据在中间怎么走:路由与网关
6.1 为什么必须有网关
二层(交换机 + MAC)只能在一个广播域里转发。192.168.1.10 想访问 10.0.1.5,它们根本不在一个广播域,MAC 寻址完全够不着。
跨网段必须靠三层转发,于是需要两样东西:
网关 → 告诉主机"出不了本网段,就把包交给谁"
路由 → 告诉中间设备"下一步该往哪踢"
6.2 网关和路由分别是什么
| 网关(Gateway) | 路由(Routing) | |
|---|---|---|
| 是什么 | 一个 IP 地址,本网段的出口 | 一套决策规则(路由表) |
| 谁用 | 主机用 | 主机和转发设备都用 |
| 回答什么 | "我出不去,交给谁?" | "交给我之后,我再往哪?" |
| 类比 | 小区大门 | 门卫手里的路线图 |
网关是主机的视角,路由是转发设备的视角。但主机自己也有一张路由表(至少一条直连 + 一条默认)。
6.3 一次跨网段的完整过程
192.168.1.0/24 10.0.0.0/30 10.0.1.0/24
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PC │ │ R1 │ │ R2 │ ┌────────┐
│ 192.168.1.10 │────────▶│ 192.168.1.1 │────────▶│ 10.0.0.2 │───────▶│ Server │
│ /24 │ │ 10.0.0.1 │ │ 10.0.1.1 │ │10.0.1.5│
└──────────────┘ └──────────────┘ └──────────────┘ └────────┘
网关=.1 两边的"门" 网关=.1
① PC 要发给 10.0.1.5 → 不在本网段 → 查路由 → 匹配默认路由 → 下一跳是网关 192.168.1.1
② PC 需要网关的 MAC
→ ARP 广播"谁是 192.168.1.1?" ← 注意:问的是网关,不是目标主机
③ PC 发出第一帧
源 MAC = PC,目的 MAC = R1 的 MAC ← 链路层只到下一跳
源 IP = 192.168.1.10,目的 IP = 10.0.1.5 ← 网络层是端到端
④ R1 收到,拆帧看目的 IP = 10.0.1.5
→ 查路由表 → 10.0.1.0/24 via 10.0.0.2
→ ARP 问 10.0.0.2 的 MAC
→ 重新封装:源 MAC = R1,目的 MAC = R2,IP 完全不变 ★ MAC 变了
⑤ R2 收到,目的网段我直连 → ARP 问 10.0.1.5 的 MAC
→ 发出最后一帧:源 MAC = R2,目的 MAC = Server,IP 依然不变
⑥ Server 回包:目的 IP 不在我的网段 → 交给它的网关 10.0.1.1 → 反向走一遍
把三帧摆在一起看:
| 链路段 | 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|---|
| PC → R1 | PC | R1 | 192.168.1.10 | 10.0.1.5 |
| R1 → R2 | R1 | R2 | 192.168.1.10 | 10.0.1.5 |
| R2 → Server | R2 | Server | 192.168.1.10 | 10.0.1.5 |
MAC 每跳重写,IP 从头到尾不变。 这就是 5.3 那句话的完整过程。
6.4 运维怎么用它排查
# ① 我有网关吗?
ip route | grep default
# 没有 default → 你根本出不了网段
# ② 去目标会走哪?
ip route get 8.8.8.8
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.10
# ↑网关 ↑出口网卡 ↑源IP
# ③ 网关通吗?
ping -c 2 192.168.1.1
| 结果 | 说明 |
|---|---|
ip route 里没有 default | 没配网关,只能内网通 |
ip route get 走的网关不对 | 路由配错了,或有两条默认路由 |
| ping 网关不通 | 二层问题:网线、VLAN、交换机、ARP |
| ping 网关通、ping 目标不通 | 三层之后的问题:路由、对端防火墙、对端主机 |
| ping 目标通、端口不通 | 不是网络层问题,去看传输层和服务 |
"ping 网关"是分水岭——它把"局部问题"和"远端问题"干净地切开了。
6.5 两个常见误区
① 网关必须和本机同网段
192.168.1.10/24 的网关不能写成 10.0.0.1——ARP 根本问不到它。
② 默认网关只能有一个有效
可以配多个,但只会用 metric 最小的那个。两条相同 metric 的默认路由会导致"时通时不通"。
七、运维视角:这套模型到底怎么用
你不是网络工程师,不需要会设计协议,需要会"按层定位问题"。
7.1 排障:按层找命令
| 层 | 出问题会怎样 | 用什么查 |
|---|---|---|
| 应用层 | 502/504、证书错、服务没起 | curl -v、nginx -t、journalctl |
| 传输层 | 端口不通、连接被拒 | ss -lntp、nc -zv |
| 网络层 | ping 不通、走错路由 | ping、ip route get、traceroute |
| 链路层 | ARP 学不到、MAC 冲突 | ip neigh、tcpdump -e |
| 物理层 | 网卡 down、链路丢包 | ethtool、ip -s link |
7.2 抓包时怎么判断
tcpdump -i any -nn port 80
| 抓到什么 | 卡在哪 |
|---|---|
| 没有 SYN | 应用层没发起 / DNS 没解析出来 |
| 有 SYN,没 SYN+ACK | 网络层或传输层(对方没听 / 被防火墙 DROP) |
| 有 SYN,回 RST | 传输层(端口没开,但机器是通的) |
| 有请求,没响应 | 应用层(服务处理慢或挂了) |
7.3 四层 vs 七层负载均衡(你项目里的东西)
| 四层(LVS) | 七层(Nginx) | |
|---|---|---|
| 工作在哪层 | 传输层(看 IP + 端口) | 应用层(看 URL、Header) |
| 能看到什么 | 只知道"要连 80 端口" | 知道"要访问 /api/users" |
| 能做什么 | 转发、负载均衡 | 路径路由、改 Header、限流、缓存 |
| 性能 | 高(不拆包) | 低一些(要解析 HTTP) |
| 你的项目 | 202 上的 LVS DR 模式 | 前端 Nginx 的 /prod-api/ 反代 |
"LVS 快、Nginx 灵活"不是玄学,是它们在第几层干活的必然结果。
八、几个容易搞混的点
① ARP 到底属于哪层?
严格说它横跨网络层和链路层(用 IP 找 MAC)。教材通常归在链路层,你按"链路层"记就行,但排障时要知道它是跨层的东西。
② TLS 属于哪层?
OSI 里对应表示层/会话层的职责(加密、会话),但实际实现位于应用层和传输层之间。所以 HTTPS 可以说成"HTTP over TLS over TCP"。
③ 为什么网络层管"主机到主机",传输层管"进程到进程"?
网络层:把包送到 192.168.1.10 这台机器 ← 不管机器上跑什么
传输层:送到机器后,再交给 80 端口那个进程 ← 才真正交付
"送到楼"和"送到房间"的区别。
④ 隧道、VPN 多出来的层怎么办?
GRE/IPsec 这类隧道协议会在原有头部外面再套一层 IP,所以有人叫它"2.5 层"或"3.5 层"。这也是为什么隧道场景下 MTU 会变小、大包容易不通。
九、共同点与不同点
共同点
- 都能提供面向连接和无连接两种通信服务机制
- 都具有层次结构
不同点
- OSI 是在协议开发前设计的,具有通用性;TCP/IP 是先有协议集、然后倒推建立模型,不适用于非 TCP/IP 网络
- 实际市场应用不同:OSI 只是理论模型,没有成熟产品;TCP/IP 已经成为**"实际上的国际标准"**
一句话记:OSI 是"先画图纸再造房子",TCP/IP 是"先盖了房子再补图纸"。 所以工程里用的永远是 TCP/IP。
疑惑:
同主机、同网段通信,到底能省掉哪一层?
一句话:这两个问题看起来都是"能不能少走一层",但真正的答案取决于——这一层有没有"下一跳"要定位。
一、先看总答案
| 场景 | 想省掉的东西 | 能省吗 | 为什么 |
|---|---|---|---|
| 同一主机的两个端口 | TCP 三次握手 | ❌ 不能 | TCP 是协议状态机,和距离无关 |
| IP 头 | ❌ 不能 | TCP 四元组要靠 IP 定位 socket | |
| 以太网帧头 | ✅ 能 | 回环没有下一跳,不需要 MAC | |
| 同一网段的两台主机 | 网关 | ✅ 能 | 直连路由没有 via |
| MAC 寻址 | ❌ 不能 | 二层转发全靠 MAC,而且指向目标主机 |
记住这张表,两个问题的答案就都有了。
二、同一主机的两个端口通信
2.1 先纠正:"端到端"不是"跨机器"
| 层 | 说法 | "端"是什么 |
|---|---|---|
| 数据链路层 | 点到点 | 相邻两个设备 |
| 网络层 | 主机到主机 | 两台机器 |
| 传输层 | 端到端 / 进程到进程 | 两个 socket |
跨主机: 192.168.1.10:54321 → 1.2.3.4:80
同主机: 127.0.0.1:54321 → 127.0.0.1:80
结构完全一样,只是 IP 恰好相同。
2.2 三次握手:省不掉
TCP 握手要完成四件事,同主机一样都得做:
| 握手要完成的事 | 同位主机为什么也必须做 |
|---|---|
| 交换初始序列号 ISN | 双方各生成随机 ISN,用于序号和确认 |
| 协商参数 | 窗口大小、MSS、SACK、时间戳 |
| 确认双向可达 | 两个 socket 都要能收发 |
| 建立全双工状态 | 两个方向独立维护序号 |
同主机只是路径短(走 loopback 不出网卡),不是省了握手。
# 验证:抓回环网卡
tcpdump -i lo -nn port 8080
# 能看到完整的 SYN → SYN-ACK → ACK
2.3 IP 头:省不掉
IP 头在这里不是"用来找路",而是用来标识 socket 端点:
① TCP 四元组靠它
源 IP : 源端口 ←→ 目的 IP : 目的端口
127.0.0.1:54321 ←→ 127.0.0.1:8080
② 路由查找仍然要做(命中 local 表)
ip route get 127.0.0.1
# local 127.0.0.1 dev lo src 127.0.0.1
③ iptables / 防火墙在 IP 层生效
iptables -A INPUT -i lo -j ACCEPT # 很多系统默认放行 lo
封了 lo,127.0.0.1 也会被拦——说明它确实过了 IP 层。
2.4 以太网帧头:可以省
帧头的核心是源 MAC 和目的 MAC,作用是"找到下一跳的网卡"。而回环上:
- 没有交换机,不需要下一跳 MAC
- 没有 ARP,因为没有链路层寻址
- 数据在内核内存里直接转交
# 抓 lo:输出从 IP 头开始,没有 ether 段
tcpdump -i lo -nn
# 12:00:01 IP 127.0.0.1.54321 > 127.0.0.1.8080: Flags [S] ...
# 抓 eth0:能看到 MAC
tcpdump -i eth0 -nn -e
# 12:00:01 00:0c:29:ab:cd:ef > 00:50:56:11:22:33, ethertype IPv4 ...
顺带:
lo的 MTU 是 65536(ip link show lo可见),远大于以太网的 1500,所以回环基本不分片。
2.5 真正"什么都不加"的:Unix Domain Socket
TCP: 应用 → TCP → IP →(lo)→ IP → TCP → 应用
UDS: 应用 → 内核 socket 缓冲区 → 应用
没有 IP、没有端口、没有握手、没有校验和。 这才是同机通信里最快的方式。
/var/run/docker.sock # Docker
/var/lib/mysql/mysql.sock # MySQL
一个绝佳对照:连本机 MySQL 的两种方式
mysql -h 127.0.0.1 -P 3306 -u root -p # 走 TCP,有三次握手
mysql -S /var/lib/mysql/mysql.sock -u root -p # 走 UDS,无握手
运维坑:开了
skip-networking后,-h 127.0.0.1连不上,但-S socket还能连——因为它们根本不是同一条路。
2.6 特别注意:容器是"同物理机",但不是"同主机"
容器A (172.17.0.2) ──veth──┐
├── docker0 网桥 ── veth ── 容器B (172.17.0.3)
容器A 的网络命名空间 └─ 宿主机命名空间
容器之间通信:IP 头 + 以太网帧头 + ARP,一样都不能少。
"同一台物理机" ≠ "同一个网络命名空间"。这条对做 Docker / K8s 的人特别重要。
三、同一网段的两台主机通信
3.1 网关:不需要
因为目的地址在直连网段里,路由表直接命中:
ip route
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10
# ↑ 只有出口网卡,没有 via
via 就是"要不要找网关"的分水岭:
| 路由条目 | 有 via? | 含义 |
|---|---|---|
192.168.1.0/24 dev eth0 | ❌ | 直连,直接发 |
default via 192.168.1.1 | ✅ | 交给网关 |
10.0.0.0/8 via 192.168.1.254 | ✅ | 交给网关 |
3.2 MAC 寻址:必须要,而且指向目标主机
① PC1 想发给 192.168.1.20
一算:同网段 → 不走网关
② ARP 广播:"谁是 192.168.1.20?"
→ PC2 回答:"我是,我的 MAC 是 B"
③ PC1 封装帧
源 MAC = A
目的 MAC = B ← 直接就是目标主机
④ 交换机查 MAC 表 → 从 B 连着的那条线发出去
交换机只认 MAC、不认 IP。 没有 MAC,它根本不知道该往哪个口发。
3.3 同网段 vs 跨网段
| 同网段 | 跨网段 | |
|---|---|---|
| 网关 | 不用 | 必须用 |
| ARP 问谁 | 目标主机 | 网关 |
| 目的 MAC | 目标主机 | 网关 |
| 目的 IP | 目标主机 | 目标主机(不变) |
| 谁转发 | 交换机(二层) | 路由器(三层) |
跨网段:IP 找网关,MAC 也找网关。
同网段:IP 直接找主机,MAC 也直接找主机。
3.4 什么情况下真的没有 MAC
MAC 是以太网的地址,换一种链路层技术就没有了:
| 链路类型 | 有 MAC | 说明 |
|---|---|---|
| 以太网 / Wi-Fi | ✅ | 最常见 |
| 回环 lo | ❌ | 同机内部,内存转发 |
| PPP / 串行链路 | ❌ | 严格点对点,只有两端 |
| WireGuard 等 VPN | ❌ | 虚拟点对点 |
| InfiniBand | ❌ | 用自己的 LID 寻址 |
判断标准:有"多个设备共享介质"就需要链路层地址;严格点对点就不需要。
四、把两个问题合成一条规律
看起来是两件事,其实是同一个判断:
问题:这一层能不能省?
答案:看它有没有"下一跳"要定位。
回环通信:没有下一跳 → 不需要帧头
但仍需要 IP(因为要定位 socket)
同网段: 有下一跳(目标主机)→ 必须有 MAC,且指向目标主机
跨网段: 有下一跳(网关)→ 必须有 MAC,且指向网关
核心结论:
链路层地址的目的,永远是"下一跳",而不是"最终目标"。
没有下一跳(回环)→ 不需要链路层头。
有下一跳 → 必须有,只是"是谁"取决于同网段还是跨网段。
五、验证命令汇总
# 【同主机】
tcpdump -i lo -nn port 8080 # 能看到三次握手
tcpdump -i lo -nn # 输出从 IP 头开始,没有 ether 段
ss -tan | grep 127.0.0.1 # 看到 ESTABLISHED
ip route get 127.0.0.1 # local ... dev lo
ip link show lo # 看 MTU 65536
# 【同网段】
ip route get 192.168.1.20 # 没有 via → 同网段直连
ip neigh show 192.168.1.20 # lladdr 是目标主机的 MAC
tcpdump -i eth0 -nn -e host 192.168.1.20 # 看目的 MAC
# 【容器之间】
docker exec -it 容器 tcpdump -i eth0 -nn -e # 有完整以太网头
六、面试速答
Q:同主机的两个端口通信要走三次握手吗?
要。TCP 是协议状态机,握手用来交换 ISN、协商参数、确认双向可达,和两台机器距离无关。同主机只是走 loopback 不出网卡,快在路径不在协议。
Q:同主机通信要加 IP 头吗?
要。TCP 四元组里包含 IP,内核要靠它找对应的 socket;防火墙也在 IP 层。但要加以太网帧头吗?不要——回环没有下一跳,不需要 MAC。
Q:同网段通信需要网关吗?
不需要。路由表命中的是直连路由,没有
via。但必须用 MAC,而且 ARP 问的是目标主机,不是网关。
Q:为什么同网段反而更依赖 MAC?
因为"同网段"的定义就是"我能用 ARP 直接问到目标主机的 MAC"。二层转发靠 MAC 表,没有 MAC 就送不出去。