Skip to content

LV010-IP地址与子网掩码 ​

一、 IPv4 地址与掩码基础 ​

1. 点分十进制与 32 位二进制 ​

IPv4 地址本质上是一个 32 位二进制数。为了好写,习惯按 8 位一组转成十进制,用点隔开,叫"点分十进制":

text
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.011111111.00000000.00000000.000000008/8
255.255.0.011111111.11111111.00000000.0000000016/16
255.255.255.011111111.11111111.11111111.0000000024/24
255.255.255.192…11111111.1100000026/26

3. CIDR 写法 ​

"CIDR 写法"就是斜杠加网络号位数。192.168.16.30/24 和"IP 加写全掩码"是同一件事的两种表达,两者完全等价。

注意掩码位数不一定是 8 的倍数:/26 表示前 26 位是网络号,剩下的 6 位是主机号,此时掩码的写法要靠位数反推,而不是靠"哪一段是 255"来判断。

二、 判断"在不在同一个网段" ​

1. 按位与运算 ​

这是网络配置里最常用、也最容易被忽略的一次计算。规则是把 IP 和掩码逐位做与运算,得到"网络地址":

text
      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:

text
      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:

text
      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,所以同网段。

IP 与掩码逐位相与得到网络地址

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 个地址):

名称怎么来的具体值能不能分配给设备
网络地址主机位全 0192.168.16.0不能,代表"这个网络本身"
广播地址主机位全 1192.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. 两条转发规则 ​

网关(默认网关)就是"出了本网段之后,第一站交给谁"。 规则很清晰:

text
目的 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 里,改地址要重新编译:

参数值作用
本机 IP192.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() 里的顺序是"先认网卡、再起协议栈、最后登记接口":

c
// 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. 参考资料 ​


本文档由 markdowncli 技能辅助生成