我们在网络配置中,设置路由器或者配置静态 IP 地址时,经常会遇到很重要的一步:设置子网掩码。很多人习惯性地填上 255.255.255.0,至于它到底是什么意思,可能还真没仔细想过。

如果去互联网上查资料,通常也很难一下看明白。上来就是“网络位”“主机位”“二进制转换”之类的一堆概念,看着就有点头大。
熟悉我的朋友可能知道,我大学虽然学的是管理学专业,但曾经立志从事网络行业,所以花“重金”学习过思科 CCNA。对局域网、广域网、路由、交换这些东西,都系统地学习过,也认真折腾过。
这么多年过去,广域网的一些知识因为缺少实践,已经逐渐遗忘了。但平时工作中,我依然经常接触局域网、服务器和各种网络设备,有些东西反而因为长期实践,理解得比以前更深。
而在给企业配置网络的过程中,我也发现,即使是经常接触网络设备的人,对子网掩码到底是怎么回事,也未必真的理解。
所以这篇文章,尝试用我自己的理解,聊聊子网掩码到底是什么。
网络数据是怎么传输的
OSI 七层模型把网络通信划分成物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。但实际使用的网络体系更多是 TCP/IP 模型,它把一些层进行了合并,结构也更加简单。不管采用什么模型,我们不妨直接看看,一段数据到底是怎么发出去的。

假设我们打开浏览器,访问 http://www.hitoy.org。
首先,浏览器通过 DNS 查询 www.hitoy.org 对应的 IP 地址,然后与服务器的 80 端口建立 TCP 连接。
连接建立后,浏览器生成 HTTP 请求数据:
GET/ HTTP/1.1
Host: www.hitoy.org
User-Agent: curl
接下来,这段数据交给操作系统的网络栈。网络栈就像给一封信一层一层加“信封”:传输层加上 TCP 信息,网络层加上 IP 信息,数据链路层再加上 MAC 信息。最后,这些数据交给网卡,转换成电信号、光信号或者无线信号,真正发送出去。

对于一个准备发送的数据包来说,应用程序(浏览器)已经确定了目标 IP 地址和端口号,那么问题来了:数据链路层需要的 MAC 地址,又是从哪里来的?
ARP 与 MAC 地址
在局域网(以太网)中,如果设备不知道某个 IP 对应的 MAC 地址,就会通过 ARP(地址解析协议)查询。系统会在局域网中发送一个 ARP 广播,拥有这个 IP 的设备收到后返回自己的 MAC 地址,系统再把这个对应关系缓存起来。整个过程由操作系统网络栈完成,应用程序不需要参与。

不过,如果目标 IP 不在当前局域网,就不能直接 ARP 查询目标设备的 MAC,而是应该把数据交给网关。那么,系统怎么知道目标 IP 是不是在本地网络?
这时候就用到了子网掩码。
子网掩码如何工作
网络栈会把本机 IP 和目标 IP,分别与子网掩码进行二进制按位 AND 运算。比如:
本机 IP: 192.168.1.10
目标 IP: 192.168.1.20
子网掩码: 255.255.255.0
把每一位转换成二进制后进行 AND:
| 第1段 | 第2段 | 第3段 | 第4段 | |
|---|---|---|---|---|
| 本机 IP | 192 11000000 | 168 10101000 | 1 00000001 | 10 00001010 |
| 子网掩码 | 255 11111111 | 255 11111111 | 255 11111111 | 0 00000000 |
| 运算结果 | 192 | 168 | 1 | 0 |
所以:
192.168.1.10 AND 255.255.255.0 = 192.168.1.0
192.168.1.20 AND 255.255.255.0 = 192.168.1.0
两个结果相同,就说明它们属于同一个网络。
如果目标是 8.8.8.8:
8.8.8.8 AND 255.255.255.0 = 8.8.8.0
结果不同,就说明目标不在当前网络,需要把数据交给网关。
所以,子网掩码其实就是一个筛子:通过二进制 AND 运算,把 IP 地址中用于表示网络的部分“筛”出来,然后比较本机和目标是不是属于同一个网络。
再理解网络位和主机位
讲到这里,又绕不开“网络位”和“主机位”。这是从网络层来理解的,简单来说,网络位就是网络的 ID,主机位就是这个网络里具体主机的 ID。同一个网络里的主机,通常可以直接进行二层通信;如果目标不属于这个网络,就需要通过网关转发。
这样说可能还是有点抽象,我们换个角度,从数据链路层来看,就很好理解了。
当网络栈拿到一个网络层的 IP 数据包时,数据包里已经有了目标 IP 地址。这时候,网络栈要做的事情其实很简单:
这个数据包,是直接发给目标主机,还是发给网关:如果目标 IP 和本机属于同一个网络,就需要找到目标主机的 MAC 地址,然后把这个 MAC 地址写进以太网帧头;如果目标 IP 不属于本地网络,就找到网关的 MAC 地址,把网关的 MAC 写进帧头。
而判断的方法,就是利用本机的 IP 地址 + 子网掩码,与目标 IP 地址进行比较,所以从这个角度看,子网掩码其实一点都不神秘。它只是帮助网络栈判断:目标 IP 属不属于“我这个网络”?
属于,就直接找目标主机的 MAC;不属于,就找网关的 MAC。
总结
应用程序通过 socket 等系统接口,指定通信的目标 IP 和端口。协议栈根据应用程序提供的数据、端口和 IP,一层层封装成数据包。
到了数据链路层,需要知道这个数据帧应该发往哪里。协议栈会根据本机 IP、子网掩码和目标 IP进行计算:如果目标在本地网络,就查找目标主机的 MAC;如果不在本地网络,就使用网关的 MAC。
从二层的角度看,子网掩码其实就这么简单:它帮助协议栈确定网络边界,从而决定数据是直接发给目标主机,还是交给网关。
所以,255.255.255.0 并不是一个需要死记硬背的“标准答案”,只是最常见的一种子网掩码而已。
评论0
欢迎分享你的看法,也欢迎补充不同的实践经验。