LV010-IP地址与子网掩码
一、 IPv4 地址与掩码基础
1. 点分十进制与 32 位二进制
IPv4 地址本质上是一个 32 位二进制数。为了好写,习惯按 8 位一组转成十进制,用点隔开,叫"点分十进制":
192 . 168 . 16 . 30
↓ ↓ ↓ ↓
11000000 10101000 00010000 00011110这 32 位被分成两部分:
- 网络号:前面若干位,标识"在哪个网络里";
- 主机号:后面若干位,标识"网络里的哪台设备"。
分界点在哪,由子网掩码决定。本项目的板子地址是 192.168.16.30,掩码 255.255.255.0,下面都用这一组来推演。
2. 子网掩码:一把"量出网络号"的尺子
掩码的规则很简单:
- 1 的位置表示"这一位属于网络号";
- 0 的位置表示"这一位属于主机号";
- 掩码里 1 必须连续,中间不能断开。
| 掩码 | 二进制 | 网络号位数 | CIDR 写法 |
|---|---|---|---|
| 255.0.0.0 | 11111111.00000000.00000000.00000000 | 8 | /8 |
| 255.255.0.0 | 11111111.11111111.00000000.00000000 | 16 | /16 |
| 255.255.255.0 | 11111111.11111111.11111111.00000000 | 24 | /24 |
| 255.255.255.192 | …11111111.11000000 | 26 | /26 |
3. CIDR 写法
"CIDR 写法"就是斜杠加网络号位数。192.168.16.30/24 和"IP 加写全掩码"是同一件事的两种表达,两者完全等价。
注意掩码位数不一定是 8 的倍数:/26 表示前 26 位是网络号,剩下的 6 位是主机号,此时掩码的写法要靠位数反推,而不是靠"哪一段是 255"来判断。
二、 判断"在不在同一个网段"
1. 按位与运算
这是网络配置里最常用、也最容易被忽略的一次计算。规则是把 IP 和掩码逐位做与运算,得到"网络地址":
192.168.16.30 11000000.10101000.00010000.00011110
& 255.255.255.0 11111111.11111111.11111111.00000000
-----------------------------------------------------------
192.168.16.0 11000000.10101000.00010000.00000000 ← 网络地址再看 PC 侧。假设 PC 配的是 192.168.16.100:
192.168.16.100 11000000.10101000.00010000.01100100
& 255.255.255.0 11111111.11111111.11111111.00000000
-----------------------------------------------------------
192.168.16.0 ← 与板子的网络地址相同 ⇒ 同一个网段如果 PC 图省事填了 192.168.17.100:
192.168.17.100 & 255.255.255.0 = 192.168.17.0 ≠ 192.168.16.0网络地址不同,就不在同一个网段。同网段才能直接互相通信,不同网段必须经过路由器——这正是 LV015-网关与跨网段通信 要讲的事。
2. 一个更直观的判断法
不用每次都做二进制运算,记住这一条就够用:
掩码是 /24 时,看前三段数字是否完全相同。
192.168.16.30 与 192.168.16.100 前三段都是 192.168.16,所以同网段。
3. 掩码写错的典型现象
掩码不是 /24 时(比如 /26),就不能只看"段"了,必须回到按位与。这是"掩码写错"为什么会导致"看起来地址是对的,就是不通":
(1)两边掩码不一致。板子按 /24 认为 192.168.16.30 与 192.168.16.130 同网段,PC 却按 /26 认为不同网段,于是 PC 把包发给了网关,而直连场景下这个网关根本不存在。
(2)掩码写成了非连续 1。比如 255.255.0.255。这种掩码在 PC 上通常直接被拒绝,在嵌入式侧则可能被静默接受,算出谁都看不懂的网络地址。
(3)只改 IP 没改掩码。把板子从 192.168.16.30 改成 192.168.1.30 却忘了同步 PC 的掩码,两边算出的网络地址自然对不上。
所以排查"ping 不通"时,第一步就是两边并排核对 IP 与掩码四个数字,而不是去查网关。
三、 几个必须记住的特殊地址
1. 网络地址与广播地址
以 192.168.16.0/24 为例(主机号 8 位,共 256 个地址):
| 名称 | 怎么来的 | 具体值 | 能不能分配给设备 |
|---|---|---|---|
| 网络地址 | 主机位全 0 | 192.168.16.0 | 不能,代表"这个网络本身" |
| 广播地址 | 主机位全 1 | 192.168.16.255 | 不能,代表"本网段所有设备" |
| 可用主机地址 | 其余 | 192.168.16.1 ~ 192.168.16.254 | 可以,共 254 个 |
还有一个不能忘:网关地址必须是同网段内的一台设备。所以 192.168.16.1 这种"网段内第一个可用地址"成了家用路由器的惯例。
2. 私有地址
下面这几个网段被 RFC 1918 划为私有地址,只能在内网用,不能在公网上被路由:
| 范围 | 掩码 | 可用地址数 |
|---|---|---|
| 10.0.0.0 ~ 10.255.255.255 | /8 | 约 1677 万 |
| 172.16.0.0 ~ 172.31.255.255 | /12 | 约 104 万 |
| 192.168.0.0 ~ 192.168.255.255 | /16 | 约 6.5 万 |
这样做的好处是"内网地址可以重复使用":你家用 192.168.16.x,邻居家也可以用 192.168.16.x,互不冲突——因为出门就换成公网地址了,机制见 LV015-网关与跨网段通信 第四节。
3. 回环、链路本地与 0.0.0.0
| 网段 | 用途 |
|---|---|
| 127.0.0.0/8 | 回环地址(127.0.0.1 就是"本机") |
| 169.254.0.0/16 | 链路本地地址,没拿到 IP 时自动使用(见 LV040-DHCP与IP地址自动获取 第五节) |
| 0.0.0.0/8 | 表示"本机/任意",DHCP 客户端起步时用它做源地址 |
四、 网关:不同网段时该找谁
1. 两条转发规则
网关(默认网关)就是"出了本网段之后,第一站交给谁"。 规则很清晰:
目的 IP 与我在同一网段 → 直接 ARP 目的 IP,自己把帧发出去
目的 IP 与我不同网段 → 把帧发给网关(目的 MAC 用网关的 MAC)2. 两个必须理解的点
(1)网关本身必须在同一网段内。因为要发给它,就得先 ARP 出它的 MAC;跨网段的设备是 ARP 不到的。
(2)同网段通信根本不看网关。这点很关键——直连实验里板子和 PC 是 192.168.16.30 / 192.168.16.100,全程走直连路由,网关填不填、填得对不对,都不影响 ping。
所以遇到"ping 不通"时,第一件事是核对两边是否同网段,而不是先去查网关。网关本身的完整机制(路由表、最长前缀匹配、跨网段时帧头怎么变)见 LV015-网关与跨网段通信。
五、 本项目的网络参数
1. 参数写在哪
三个值都写在 atk-f103/Components/lwip-2.1.3/port/lwip_comm.h 里,改地址要重新编译:
| 参数 | 值 | 作用 |
|---|---|---|
| 本机 IP | 192.168.16.30 | 板子自己的地址 |
| 子网掩码 | 255.255.255.0 | 决定"哪些地址算同网段" |
| 网关 | 192.168.16.1 | 跨网段时的第一站;本实验直连用不到 |
在 lwip_comm.h 里它们是按字节定义的宏(LWIP_LOCAL_IP0 ~ LWIP_LOCAL_IP3 等),初始化时由 IP4_ADDR() 拼成 lwIP 的地址结构。
2. 为什么选 192.168.16.x
为什么故意选 192.168.16.x 这个不常见的网段?因为它和家用路由器默认的 192.168.1.x / 192.168.0.x 错开。如果把板子设成 192.168.1.30,那么当你把板子接到家里路由器上时,很可能与路由器自己的地址段撞车,排查起来会多一层麻烦。
3. 参数是怎么被用上的
lwip_comm_init() 里的顺序是"先认网卡、再起协议栈、最后登记接口":
// Components/lwip-2.1.3/port/lwip_comm.c
if (DM9000_Init() != 0U) { return LWIP_COMM_DM9000_ERR; } /* 先认卡 */
lwip_init(); /* 再起协议栈 */
IP4_ADDR(&ipaddr, LWIP_LOCAL_IP0, LWIP_LOCAL_IP1, LWIP_LOCAL_IP2, LWIP_LOCAL_IP3);
IP4_ADDR(&netmask, ...); IP4_ADDR(&gw, ...); /* 填三个参数 */
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
netif_set_default(&gnetif); netif_set_up(&gnetif);这套流程的每一行为什么这么排,见 LV015-lwIP配置与初始化 第四节。
六、 小结与参考资料
1. 本篇小结
- IPv4 是 32 位,分成网络号与主机号,分界由掩码决定;掩码写全与 CIDR 写法等价。
- 判断同网段的方法是
IP & 掩码,比较得到的网络地址;/24 时可以直接看前三段。 - 网络地址、广播地址不能分配给设备;网关必须是同网段设备。
- 私有地址(含
192.168.0.0/16)用于内网,出门靠 NAT。 - 同网段不走网关:排查"不通"要先核对网段,而不是先怀疑网关。
- 本工程把 IP、掩码、网关写成
lwip_comm.h里的宏,选192.168.16.x是为了避开家用路由器的常用网段。
2. 参考资料
- 本工程网络参数:
lwip_comm.h - 网络参数打印与初始化:
lwip_comm.c - 地址处理实现:
ip4_addr.c - 实验中的实际使用:LV020-网络通信实验 第一节
本文档由 markdowncli 技能辅助生成