Files
cs-note/hhs/NETWORK/01-基础概念/03-寻址体系MAC-IPTPort.md
T
2026-05-27 00:12:00 +08:00

220 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, MAC地址, IP地址, 端口号]
create time: 2026-05-17 22:30
---
# 寻址体系:MAC / IP / Port
## 概述
网络中的每个端点需要三层地址才能精确定位到一个进程:**MAC 地址**(物理层/链路层)定位到哪台设备、**IP 地址**(网络层)定位到哪个子网、**端口号**(传输层)定位到哪个进程。三层地址组合起来,就是经典的 `ip:port` 定位公式。
> [!QUESTION] 为什么需要三种地址?一层不够吗?
> 每种地址解决不同尺度的问题。MAC 在同一个广播域内有效,但路由器不转发广播——跨网段必须用 IP 路由。IP 能到达目标主机,但不区分进程——同一台服务器可能跑着 Web、数据库、邮件等多个服务,所以需要端口来分发。
## 一、MAC 地址(48 位)
### 基本结构
```
前 3 字节 后 3 字节
───────────── ─────────────
OUI (厂商编号) NIC 序列号
由 IEEE 分配 由厂商自定
```
示例:`aabb.ccdd.eeff` = `AA:BB:CC:DD:EE:FF`
- 前三个字节 `AA:BB:CC` → OUI,代表厂商
- 后三个字节 `DD:EE:FF` → 设备唯一序列
### MAC 地址类型
| 类型 | 格式 | 含义 |
|------|------|------|
| 单播 | LSB=0 | 发给单个设备 |
| 广播 | `ff:ff:ff:ff:ff:ff` | 发给局域网内所有设备 |
| 组播 | LSB=1 | 发给一组设备 |
### ARP 地址解析
当知道一个主机的 **IP 地址** 时,需要通过 ARP 协议找到它的 **MAC 地址**。
```mermaid
sequenceDiagram
participant Src as 源主机<br/>192.168.1.10/?.mac
participant Bcast as 局域网广播
participant Dst as 目标主机<br/>192.168.1.20/aa:bb:cc:11:22:33
participant Cache as 源主机 ARP 缓存
Src->>Bcast: ARP Request "192.168.1.20 是谁?→ ff:ff:ff:ff:ff:ff"
Dst-->>Src: ARP Reply "我是!MAC = aa:bb:cc:11:22:33"
Src->>Cache: 写入缓存条目 (Linux 默认 ≈ 30s, Windows ≈ 15~45s, 可配置)
Note over Src,Dst: 之后的通信直接用此 MAC,不再发 ARP
```
### ARP 缓存查看与管理
```bash
# Linux
$ ip neigh show # 等价于 arp -n
192.168.1.20 dev eth0 lladdr aa:bb:cc:dd:ee:ff STALE
$ ip neigh del 192.168.1.20 dev eth0 # 删除缓存条目
# macOS / Windows
$ arp -a
```
## 二、IP 地址(IPv4 32 位 / IPv6 128 位)
### IPv4 首部结构
```
版本(4 bits) IHL(4 bits) DSCP(8 bits) Total Length(16 bits)
...
Identification(16 bits) | DF/MF | Fragment Offset(13 bits)
TTL(8 bits) | Protocol(8 bits) | Header Checksum(16 bits)
Source Address(32 bits)
Destination Address(32 bits)
Options (可选)...
```
### IPv4 vs IPv6
| 特性 | IPv4 | IPv6 |
|------|------|------|
| 地址长度 | 32 bit (4 字节) | 128 bit (16 字节) |
| 地址数量 | ~43 亿 (2³²) | ~3.4×10³⁸ (2¹²⁸) |
| 表示法 | `192.168.1.1` | `2001:0db8::1` |
| 首部固定长度 | 20 bytes(可变选项更长) | 40 bytes(固定) |
| Checksum | ✅ 有 | ❌ 无(依赖上层校验) |
| NAT | 广泛使用(缓解地址耗尽) | 不需要(地址充足) |
| SLAAC | — | 支持无状态自动配置 |
| 组播 | 有限支持 | 原生支持 |
| 地址解析 | ARP(广播) | NDP / Neighbor Discovery(组播,替代 ARP) |
### IPv6 地址表示与压缩
IPv6 地址共 128 位,用冒号分隔为 8 组,每组 4 个十六进制数:
```
完整写法: 2001:0db8:0000:0000:0000:0000:0000:0001
压缩规则 1 — 每组前导零可省略: 2001:db8:0:0:0:0:0:1
压缩规则 2 — 连续全零组用 :: 替代(仅一次): 2001:db8::1
```
> [!QUESTION] `::` 能用几次?
> 只能用**一次**。如果出现两个 `::`,解析器无法确定每组省略了多少个零,地址就会歧义。
### IPv6 特殊地址
| 地址 | 用途 |
|------|------|
| `::1` | 环回地址,等价于 IPv4 的 `127.0.0.1` |
| `::` | 未指定地址,等价于 IPv4 的 `0.0.0.0` |
| `fe80::/10` | 链路本地地址(Link-Local),同一链路自动通信 |
| `ff00::/8` | 组播地址 |
> 更多 IPv6 细节见 [[hhs/NETWORK/03-网络层/03-IPv6地址与扩展头部]]。
### IP 地址分类(历史)
| 类别 | 首字节范围 | 默认掩码 | 可用主机数 | 用途 |
|------|-----------|---------|-----------|------|
| A | 1–126 | /8 | 16,777,214 | 大型组织 |
| B | 128–191 | /16 | 65,534 | 中型组织 |
| C | 192–223 | /24 | 254 | 小型网络 |
| D | 224–239 | — | — | 组播 |
| E | 240–255 | — | — | 保留 |
> [!warning] CIDR 已淘汰分类编址
> 现代网络全部使用 **CIDR(Classless Inter-Domain Routing)** 无类编址,子网掩码可以是任意位数(如 /23、/27)。
> CIDR 用"前缀长度"取代了固定的 A/B/C 类划分,例如 `192.168.1.0/24` 表示前 24 位是网络号,剩余 8 位是主机号。
> 更多细节见 [[hhs/NETWORK/03-网络层/02-CIDR与子网划分]]。
### 特殊 IP 地址
| 地址 | 用途 |
|------|------|
| `127.0.0.1` / `::1` | 环回地址(Loopback),本机内部通信 |
| `0.0.0.0` | 表示"本机所有网卡"(服务端 bind 时常用) |
| `169.254.x.x` | 链路本地地址(DHCP 失败时自动分配) |
### 私有 IP 地址段
互联网上的路由器**不会转发**来自以下范围的数据包,它们仅用于内网,通过 NAT 转换为公网 IP 后才能访问互联网:
| 类别 | 地址范围 | CIDR | 可用地址数 |
|------|---------|------|-----------|
| A 类 | `10.0.0.0` ~ `10.255.255.255` | `10.0.0.0/8` | ~1677 万 |
| B 类 | `172.16.0.0` ~ `172.31.255.255` | `172.16.0.0/12` | ~104 万 |
| C 类 | `192.168.0.0` ~ `192.168.255.255` | `192.168.0.0/16` | ~6.5 万 |
> [!tip] 私有地址 + NAT = 解决 IPv4 耗尽
> 一个公网 IP 可以通过 NAT 映射背后成百上千个私有 IP,这就是为什么 IPv4 至今仍在大规模使用。详见 [[hhs/NETWORK/03-网络层/08-NAT原理与应用]]。
## 三、端口号(16 位)
### 端口范围
| 范围 | 名称 | 说明 |
|------|------|------|
| 0–1023 | 熟知端口 (Well-Known) | 预分配给标准服务(HTTP:80, HTTPS:443, SSH:22, DNS:53) |
| 1024–49151 | 注册端口 (Registered) | 申请注册的商业软件 |
| 49152–65535 | 动态端口 (Ephemeral) | 客户端临时分配,用完即释放 |
### 服务端 vs 客户端端口
```mermaid
flowchart LR
Client["客户端 192.168.1.100:54321"] -->|"SYN"| Server["服务端 10.0.0.1:80"]
Server -->|"SYN-ACK"| Client
Client -->|"ACK"| Server
style Client fill:#DDA0DD,color:#000
style Server fill:#98FB98,color:#000
```
- **服务端端口**:固定且知名(如 80),告诉客户端"我在哪"
- **客户端端口**:操作系统动态分配(49152–65535),保证连接的唯一标识 `(src_ip, src_port, dst_ip, dst_port)`
### 常见端口速查
| 端口 | 协议 | 服务 |
|------|------|------|
| 20 | FTP-Data | 文件传输数据通道 |
| 21 | FTP | 文件传输控制通道 |
| 22 | SSH | 安全远程登录 |
| 25 | SMTP | 邮件发送 |
| 53 | DNS | 域名解析 |
| 80 | HTTP | Web 网站 |
| 443 | HTTPS | 加密 Web |
| 993 | IMAPS | 加密邮件收取 |
| 3306 | MySQL | 数据库 |
| 5432 | PostgreSQL | 数据库 |
| 6379 | Redis | 缓存 |
| 8080 | HTTP Alt | Web 备用端口 |
## 四、完整寻址链:从请求到进程
```mermaid
flowchart TD
S["你在浏览器输入 example.com"] -->|"DNS 查询"| A["DNS 返回 93.184.216.34"]
A -->|"TCP 三次握手"| B["建立 TCP 连接<br/>src:192.168.1.100:54321 → dst:93.184.216.34:80"]
B -->|"以太网帧头"| C["Dst MAC: router的出口MAC<br/>Src MAC: 本机MAC"]
C -->|"ARP缓存"| D["如果没缓存,先发ARP请求"]
D -->|"发送 HTTP GET"| E["Web 服务器的 PID 1234<br/>nginx worker 进程读取数据"]
style S fill:#DDA0DD,color:#000
style E fill:#98FB98,color:#000
```
**结论:** 三层地址缺一不可——没有 IP 找不到机器,没有 MAC 连不上网线,没有端口不知道该交给哪个进程。
## 关联笔记
- [[hhs/NETWORK/01-基础概念/01-OSI与TCP-IP模型对比]] — 三层地址对应 OSI 的不同层级
- [[hhs/NETWORK/03-网络层/01-IPv4首部与分段重组]] — IP 首部的详细字段与分段机制
- [[hhs/NETWORK/03-网络层/02-CIDR与子网划分]] — CIDR 计算与子网划分实战
- [[hhs/NETWORK/04-传输层/01-TCP段结构与状态机]] — 四元组如何唯一标识 TCP 连接