3、网络层核心:IP协议、IPv4与IPv6、子网掩码与CIDR、路由选择基础

聊到网络层,IP协议绝对是绕不开的主角。我刚开始做全栈开发那会儿,总觉得IP层离应用层太远,写业务代码根本用不上。直到有一次排查线上超时问题,抓包一看,发现数据包在路由节点之间来回跳了二十多跳还没到目的地……嗯,从那以后我再也不敢小看网络层了。

说白了,网络层就是负责把数据包从源主机送到目标主机。它不关心你传的是什么内容,也不保证一定能送到——那是传输层的事。它只做一件事:寻址和转发

IP协议:互联网的“通用语言”

IP协议的全称是Internet Protocol,它定义了数据包在网络中传输的格式和规则。每个数据包都包含一个头部,里面最重要的就是源IP地址和目标IP地址。

我习惯把IP协议比作快递单上的寄件人和收件人地址。没有这个地址,数据包在网络里就是无头苍蝇。IP协议的核心能力有两个:

  • 寻址:给每台设备分配一个唯一的逻辑地址
  • 分片与重组:当数据包太大,超过链路层的MTU时,IP层会把它切成小块,到了目的地再拼回去
我的经验: 调试网络问题时,我经常用tcpdump抓包看IP头部的标识字段。如果看到同一个ID的数据包被分成了多个片段,说明MTU设置可能有问题。我曾经在容器环境下遇到过MTU不匹配导致的服务间通信超时,排查了整整两天才找到根因。

IPv4:老当益壮,但地址快用完了

IPv4地址是32位的,通常写成点分十进制,比如 192.168.1.1。理论上可以提供约43亿个地址。你想想看,全球几十亿人,每人手里好几台设备,这点地址哪够用?

IPv4地址的结构分为两部分:网络号主机号。网络号标识你所在的网络段,主机号标识你在该网络里的具体设备。

举个例子:192.168.1.0/24 这个网段里,192.168.1 是网络号,最后一个 0 是主机号范围。为什么是 /24?这个我们后面讲CIDR的时候再说。

IPv4地址还分成了几类:

类别 起始位 地址范围 用途
A类 0 1.0.0.0 - 126.255.255.255 大型网络
B类 10 128.0.0.0 - 191.255.255.255 中型网络
C类 110 192.0.0.0 - 223.255.255.255 小型网络
D类 1110 224.0.0.0 - 239.255.255.255 组播
E类 1111 240.0.0.0 - 255.255.255.255 保留
注意: 实际开发中,你几乎不会遇到A类、B类这种分类方式了。现在都是用CIDR来划分网络。但理解分类有助于你读懂老代码和旧文档。

IPv6:下一代协议,地址多到用不完

IPv4地址枯竭是个老生常谈的问题。IPv6把地址长度扩展到了128位,写成8组16进制数,比如 2001:0db8:85a3:0000:0000:8a2e:0370:7334

128位是什么概念?地球上每粒沙子都能分到一个IP地址。你想想看,这得有多大的空间。

IPv6相比IPv4有几个明显的变化:

  • 头部更简洁:固定40字节,没有选项字段,路由器处理更快
  • 内置安全:IPSec是IPv6的标配,不是可选项
  • 自动配置:设备可以自动生成链路本地地址,不需要DHCP
  • 没有广播:用组播和任播代替广播,减少网络噪音

我个人习惯在开发环境里同时启用IPv4和IPv6双栈。虽然大部分云服务商还是以IPv4为主,但IPv6的普及速度比我想象中快。我记得去年帮一个客户做物联网项目,他们的设备全部走IPv6,因为设备数量实在太多了,IPv4根本不够分。

子网掩码与CIDR:告别浪费,精准划分

子网掩码是个32位的数字,和IP地址做“与”运算,就能得到网络号。比如 255.255.255.0 表示前24位是网络号,后8位是主机号。

但子网掩码有个问题——它太死板了。你只能按8位、16位、24位这种边界来划分网络。这就导致了很多浪费。比如一个公司需要300个IP地址,用C类(254个)不够,用B类(65534个)又太多。

CIDR(无类别域间路由)就是来解决这个问题的。它用 /数字 来表示网络前缀的长度,不再受限于A、B、C类的边界。

举个例子:

192.168.1.0/24  → 网络号24位,主机号8位,可用地址254个
192.168.1.0/25  → 网络号25位,主机号7位,可用地址126个
192.168.1.0/26  → 网络号26位,主机号6位,可用地址62个

你看,通过CIDR,我们可以精确地划分出刚好够用的地址段。我在做微服务架构设计时,经常用CIDR来规划不同服务的网络段,避免地址冲突。

核心公式: 可用地址数 = 2^(32 - 前缀长度) - 2
减2是因为网络地址和广播地址不能用。

路由选择基础:数据包是怎么找到路的?

路由选择,说白了就是路由器决定把数据包往哪扔。每个路由器都维护着一张路由表,里面记录着目标网络和下一跳地址的对应关系。

路由选择分两种:

  • 静态路由:管理员手动配置。适合小网络,稳定但维护成本高
  • 动态路由:路由器之间自动交换信息。适合大型网络,灵活但复杂

动态路由协议又分两类:

类型 协议 特点
距离矢量 RIP 基于跳数,简单但收敛慢
链路状态 OSPF 基于链路状态,收敛快,适合大型网络
路径矢量 BGP 互联网核心协议,基于AS路径

我曾经在调试一个跨地域的微服务调用时,发现请求总是超时。抓包一看,数据包从北京绕到了美国,再绕回上海。原因是BGP路由表里有一条更优的路径没有被选上。后来调整了AS路径的权重,问题才解决。

避坑指南: 如果你在云环境里部署服务,一定要关注路由表。我曾经遇到过因为默认路由指向了错误的网关,导致所有出站流量都走不通。排查了半小时才发现是路由表配错了。

路由选择的核心原则是最长前缀匹配。什么意思呢?就是路由表里如果有多个条目匹配目标地址,路由器会选择前缀最长的那个。比如目标地址是 192.168.1.100,路由表里有 192.168.0.0/16192.168.1.0/24,路由器会选后者,因为它的前缀更长,更精确。

嗯,网络层的内容就聊到这儿。下一章我们讲传输层,到时候会聊到TCP的三次握手和四次挥手——那可是面试高频考点,也是实际开发中经常踩坑的地方。