网络到底在解决什么问题
一句话:让一台机器上的数据,准确地送到另一台机器上的某个程序里。
想象你要把一封信寄给朋友。你需要知道几件事:朋友住在哪(地址)、信怎么投递(邮政系统的层层中转)、信封上写谁收(具体的人,而不只是地址)。计算机网络做的是同一件事,只不过把「地址」「中转」「收件人」分别交给了不同的机制。
- 地址在哪:靠
IP 地址定位到具体的主机。 - 怎么投递:靠
路由器一跳一跳地转发。 - 交给谁:靠
端口号找到主机上具体的程序(浏览器、QQ、SSH)。 - 名字翻译:人记不住数字,靠
DNS把google.com翻译成 IP。
剩下的章节,基本就是把这几件事一件一件展开。
分层模型:为什么要分层
网络太复杂,于是工程师把它切成几层,每一层只管自己的事,上下层之间通过约定好的接口对接。
课本上常讲 OSI 七层模型,但实际工程里更常用的是 TCP/IP 四层模型。两者大致能对上。理解的关键是:每一层都把上层的数据当成「不透明的货物」,加上自己的「包装」(首部),再交给下一层。 这个过程叫封装,接收端反过来一层层拆开,叫解封装。
IP 地址 (IPv4)
IPv4 地址就是一个 32 位的二进制数,为了方便人读,写成「点分十进制」。
比如 192.168.1.10,它其实是 32 个 0/1:
192 .168 .1 .10
11000000.10101000.00000001.00001010
# 每一段(8位)叫一个「八位组 octet」,范围 0~255
# 4 段 × 8 位 = 32 位,所以 IPv4 总共约 43 亿个地址
一个 IP 地址在概念上分成两部分:网络号(标识你在哪个网段)和 主机号(标识网段里的哪台机器)。具体哪几位是网络号,由子网掩码决定——这正是下一节的主角。
历史包袱:A/B/C 类地址
早期用「分类编址」,按第一段大小划分。现在基本被 CIDR 取代了,但面试和老文档里还会出现,了解即可:
| 类别 | 首段范围 | 默认掩码 | 典型用途 |
|---|---|---|---|
| A 类 | 1 – 126 | /8 (255.0.0.0) | 超大型网络 |
| B 类 | 128 – 191 | /16 (255.255.0.0) | 中型网络 |
| C 类 | 192 – 223 | /24 (255.255.255.0) | 小型网络/家用 |
子网掩码与 CIDR —— 核心中的核心
子网掩码回答一个问题:这个 IP 里,前面多少位是「网络」,后面多少位是「主机」。
掩码也是 32 位,规则非常简单:前面连续的 1 标记网络号,后面连续的 0 标记主机号。 1 永远在左、0 永远在右,中间不会交错。
IP 192.168.1.10 = 11000000.10101000.00000001.00001010
掩码 255.255.255.0 = 11111111.11111111.11111111.00000000
└─────── 网络号(24位) ──────┘ └主机号(8位)┘
CIDR 写法:/24 是什么意思
现代写法直接在 IP 后面加一个斜杠和数字:192.168.1.10/24。这个 24 就是「掩码里有 24 个 1」,等价于 255.255.255.0。比起写一长串掩码,简洁多了。
三个关键计算
给定一个 IP 和掩码,你通常要算这几个东西:
- 网络地址:IP 和掩码做按位与 (AND)。代表「整个网段的名字」,主机位全为 0。
- 广播地址:主机位全为 1。发到这个地址 = 发给网段内所有机器。
- 可用主机数:主机位有
n位时,地址总数是 2ⁿ,但要减 2(去掉网络地址和广播地址),所以可用主机 = 2ⁿ − 2。
# 以 192.168.1.10/24 为例
网络地址 = 192.168.1.0 # 主机位全 0
广播地址 = 192.168.1.255 # 主机位全 1
可用范围 = 192.168.1.1 ~ 192.168.1.254
可用主机 = 2^8 - 2 = 254 台
(特例:/31 用于点对点链路时不减 2,/32 表示单个主机,这些是进阶细节。)
常见掩码对照表
| CIDR | 子网掩码 | 主机位 | 可用主机数 |
|---|---|---|---|
| /24 | 255.255.255.0 | 8 | 254 |
| /25 | 255.255.255.128 | 7 | 126 |
| /26 | 255.255.255.192 | 6 | 62 |
| /27 | 255.255.255.224 | 5 | 30 |
| /28 | 255.255.255.240 | 4 | 14 |
| /30 | 255.255.255.252 | 2 | 2 |
| /16 | 255.255.0.0 | 16 | 65534 |
口诀:CIDR 数字越大,网段越小(网络位多了,留给主机的位就少了)。
动手玩:子网计算器
输入任意 IP 和掩码,实时看到网络地址、广播地址、可用范围,以及二进制里网络位/主机位的分界线。
◑ Subnet Calculator
绿色是网络位,灰色是主机位。改一改 CIDR,看分界线怎么移动——这是理解子网最快的方式。
私有地址与 NAT
公网 IP 不够用,于是家里、公司内部都用「私有地址」,出门时再统一翻译成一个公网 IP。
有三段地址被专门留作私有,不会出现在公网上,谁都可以用:
| 范围 | CIDR | 常见场景 |
|---|---|---|
| 10.0.0.0 – 10.255.255.255 | 10.0.0.0/8 | 大型企业内网 |
| 172.16.0.0 – 172.31.255.255 | 172.16.0.0/12 | 中型网络 / Docker |
| 192.168.0.0 – 192.168.255.255 | 192.168.0.0/16 | 家用路由器 |
NAT(网络地址转换)就是路由器干的活:你家里十几台设备都是 192.168.x.x,但对外只露出运营商给的那一个公网 IP。路由器维护一张表,记住「哪个内网设备的哪个端口」对应「公网 IP 的哪个端口」,回包来的时候再翻译回去。
ip addr 里看到的地址(比如 192.168.1.x)和你在「百度搜 IP」看到的地址不一样——前者是内网地址,后者是 NAT 之后的公网出口地址。
IPv6:为什么需要它
IPv4 只有约 43 亿个地址,早就不够全球的设备分了。IPv6 把地址扩到 128 位。
128 位是什么概念?大约 3.4 × 10³⁸ 个地址——多到给地球上每一粒沙子都能分一大把。写法上改成 8 组、每组 4 个十六进制数,用冒号隔开:
完整写法:
2001:0db8:0000:0000:0000:ff00:0042:8329
# 简写规则:
# 1) 每组前导 0 可省略
# 2) 连续的全 0 组可用 :: 压缩(整个地址只能用一次)
简写后:
2001:db8::ff00:42:8329
几个常见的 IPv6 地址
::1—— 环回地址,相当于 IPv4 的127.0.0.1fe80::/10—— 链路本地地址,每个接口自动生成,只在本网段有效::/0—— 默认路由(IPv6 版的 0.0.0.0/0)
IPv6 还顺手去掉了 NAT 的必要性(地址够多,人人都能有公网地址),并内建了地址自动配置(SLAAC)。但现实是 IPv4 和 IPv6 会长期共存,叫双栈。
MAC 地址与 ARP
IP 是「逻辑地址」,可以变;MAC 是网卡出厂就刻死的「物理地址」。在同一个局域网里,真正按 MAC 找机器。
MAC 地址是 48 位,写成 6 组十六进制,比如 a4:83:e7:1f:0c:5d。前 3 组是厂商编号,后 3 组是设备序号。
问题来了:你知道对方的 IP(比如要发给 192.168.1.1),但链路层只认 MAC。怎么把 IP 翻译成 MAC?答案是 ARP(地址解析协议):
# A 想发给 192.168.1.1,但不知道它的 MAC
A 广播: "谁是 192.168.1.1?把 MAC 告诉我" # ARP 请求,全网段都收到
路由器: "是我,我的 MAC 是 a4:83:e7:1f:0c:5d" # ARP 应答
A 把这条记录缓存起来,下次直接用 # ARP 缓存
可以用 ip neigh(旧命令 arp -n)看本机的 ARP 缓存表。
DNS:把名字翻译成地址
你输入 google.com,但网络只认 IP。DNS 就是互联网的「电话簿」。
查询是一个层层向上问的过程(这里简化):
- 先问本地缓存 / hosts 文件,命中就直接返回。
- 没有就问递归 DNS 服务器(通常是运营商的,或 8.8.8.8 / 1.1.1.1)。
- 递归服务器从根域名服务器 → 顶级域(.com) → 权威服务器一路问下来,拿到 IP。
- 结果按 TTL 时间缓存起来,下次更快。
常见记录类型
| 类型 | 作用 |
|---|---|
| A | 域名 → IPv4 地址 |
| AAAA | 域名 → IPv6 地址 |
| CNAME | 别名,指向另一个域名 |
| MX | 邮件服务器 |
| TXT | 任意文本(常用于验证、SPF) |
# 查一个域名的 A 记录
$ dig +short example.com
93.184.216.34
# 看完整解析过程
$ dig example.com
端口、TCP 与 UDP
IP 把数据送到机器,端口决定交给机器上的哪个程序。TCP/UDP 决定「怎么送」。
端口是一个 16 位数字(0~65535)。一台服务器可以同时跑网站(80/443)、SSH(22)、数据库(3306) ——靠端口区分。
| 端口 | 服务 |
|---|---|
| 22 | SSH |
| 53 | DNS |
| 80 / 443 | HTTP / HTTPS |
| 3306 / 5432 | MySQL / PostgreSQL |
TCP vs UDP
| TCP | UDP | |
|---|---|---|
| 可靠性 | 保证送达、按序、重传 | 不保证,丢了就丢了 |
| 连接 | 先三次握手建连接 | 无连接,直接发 |
| 速度 | 较慢(有确认开销) | 快、延迟低 |
| 典型用途 | 网页、文件、SSH | 视频通话、游戏、DNS |
TCP 建立连接靠三次握手:
客户端 ──SYN──────────▶ 服务器 # 我要连你
客户端 ◀──SYN+ACK────── 服务器 # 好的,我也准备好了
客户端 ──ACK──────────▶ 服务器 # 收到,开始传数据
路由与网关
数据要离开本网段去外面的世界,第一站永远是「默认网关」。
当你的机器要发包时,它先判断:目标 IP 和我在同一个网段吗?(用子网掩码 AND 一下就知道)
- 在同一网段:直接通过 ARP 找到对方 MAC,本地发出去。
- 不在同一网段:交给默认网关(一般就是你的路由器,比如 192.168.1.1),由它继续往外转发。
互联网就是无数路由器接力转发的结果,每台路由器维护一张路由表,决定「去某个目标,下一跳该交给谁」。
# 看本机路由表
$ ip route
default via 192.168.1.1 dev wlan0 # 默认网关(出口)
192.168.1.0/24 dev wlan0 proto kernel # 本地网段,直连
# 追踪一个包经过哪些路由器
$ traceroute google.com
把它们串起来:打开一个网页发生了什么
这是把前面所有概念连成一条线的最佳练习。你在浏览器输入 https://example.com 后:
- ① DNS 解析:先查
example.com的 IP。本地没缓存就问递归 DNS,最终拿到93.184.216.34。 - ② 判断网段:目标 IP 不在本网段 → 包要发给默认网关。
- ③ ARP:查网关 192.168.1.1 的 MAC,封装链路层帧。
- ④ NAT:路由器把你的私有 IP 换成公网 IP 发出去,沿途无数路由器按路由表接力转发。
- ⑤ TCP 握手:和服务器的 443 端口三次握手,建立连接。
- ⑥ TLS + HTTP:加密协商完成后,发出 HTTP 请求,服务器返回网页内容。
- ⑦ 渲染:数据一路按 NAT/路由原路返回到你机器的浏览器,画面出现。
Linux 常用命令速查
你是 Arch 用户,下面这些 iproute2 工具直接拿来动手验证最快。
# —— 看自己的地址 ——
$ ip addr # 所有网卡的 IP / 掩码
$ ip -br addr # 简洁版
# —— 路由与网关 ——
$ ip route # 路由表,找 default 那行
$ ip neigh # ARP 缓存(IP↔MAC)
# —— 连通性 ——
$ ping 1.1.1.1 # 测能不能到
$ traceroute github.com # 看经过哪些跳
# —— DNS ——
$ dig +short github.com # 查 A 记录
$ resolvectl status # 看当前用的 DNS 服务器(systemd)
# —— 端口与连接 ——
$ ss -tulnp # 看本机监听了哪些端口(替代 netstat)
$ ss -tnp # 看当前 TCP 连接
# —— 抓包(进阶) ——
$ sudo tcpdump -i any port 53 # 实时看 DNS 流量
dig 看解析、用 ip route 看网关、用 ss -tnp 看建立的连接、用 tcpdump 抓一次 DNS 包。看见真实数据流动的那一刻,这些概念就真正变成你的了。