当你在浏览器输入一个网址,或者在服务器配置文件中填写IP地址时,这些看似简单的数字串背后,其实是一套精心设计的地址系统。理解IP地址和子网掩码,是理解整个互联网如何运作的起点。
IP地址是什么
IP地址(Internet Protocol Address)是互联网协议地址的简称。它就像现实世界中的门牌号,用来唯一标识网络中的每一台设备。
IPv4地址是一个32位的二进制数。但直接用二进制表示太不直观了——谁愿意记住11000000101010000000000000000001这样的数字呢?于是人们将其分成4段,每段8位(一个字节),转换成十进制后用点分隔,这就是我们熟悉的"点分十进制"表示法。
上面的二进制数就变成了:192.168.0.1
每一段的取值范围是0-255,因为8位二进制能表示的最大值是$2^8-1 = 255$。
二进制与十进制的转换
理解IP地址,必须掌握二进制转换。一个8位二进制数,每一位的权重从右到左依次是:
$$2^7, 2^6, 2^5, 2^4, 2^3, 2^2, 2^1, 2^0$$即:128, 64, 32, 16, 8, 4, 2, 1
以数字192为例:
- $192 = 128 + 64 = 2^7 + 2^6$
- 所以二进制是
11000000
反过来,二进制10101000转十进制:
- $128 + 32 + 8 = 168$
这个转换在网络计算中会反复用到,建议多练习几次。
IP地址的两部分:网络号与主机号
IP地址本质上由两部分组成:网络号(Network ID)和主机号(Host ID)。
- 网络号:标识设备所在的网络,就像"XX省XX市XX区"
- 主机号:标识该网络中的具体设备,就像"XX街道XX号"
举个例子:192.168.1.100
如果前三个数字是网络号,最后一个数字是主机号,那么:
- 网络号:
192.168.1—— 表示这是一个名为"192.168.1"的网络 - 主机号:
100—— 表示这个网络中编号为100的设备
问题来了:怎么知道前几个数字是网络号,后面几个是主机号?这就需要子网掩码来回答。
子网掩码的作用
子网掩码(Subnet Mask)是一个32位的二进制数,用来"遮罩"IP地址,区分出网络部分和主机部分。
子网掩码的规则很简单:用连续的1表示网络位,用连续的0表示主机位。
最常见的子网掩码255.255.255.0,写成二进制是:
11111111.11111111.11111111.00000000
前24位是1,后8位是0。这意味着:IP地址的前24位是网络号,后8位是主机号。
用与运算提取网络地址
把IP地址和子网掩码进行"按位与"(AND)运算,就能得到网络地址。
与运算的规则:
- 1 AND 1 = 1
- 1 AND 0 = 0
- 0 AND 1 = 0
- 0 AND 0 = 0
举例:IP地址192.168.1.100,子网掩码255.255.255.0
IP地址: 11000000.10101000.00000001.01100100 (192.168.1.100)
子网掩码: 11111111.11111111.11111111.00000000 (255.255.255.0)
------------------------------------------------
与运算结果:11000000.10101000.00000001.00000000 (192.168.1.0)
192.168.1.0就是网络地址,它代表整个网络本身,不能分配给任何设备。
IP地址的分类
在互联网早期,IP地址按首字节的数值范围分为五类:
| 类别 | 首字节范围 | 默认子网掩码 | 网络规模 |
|---|---|---|---|
| A类 | 1-126 | 255.0.0.0 | 大型网络,约1677万台主机 |
| B类 | 128-191 | 255.255.0.0 | 中型网络,约65534台主机 |
| C类 | 192-223 | 255.255.255.0 | 小型网络,254台主机 |
| D类 | 224-239 | 无 | 组播地址 |
| E类 | 240-255 | 无 | 保留地址 |
这种"有类寻址"方式如今已很少使用,现代网络普遍采用CIDR(无类别域间路由),不再受限于A/B/C类的划分。
CIDR表示法
CIDR(Classless Inter-Domain Routing,无类别域间路由)是一种更灵活的表示方式,直接在IP地址后面加上斜杠和网络位数。
比如192.168.1.0/24:
24表示前24位是网络位- 等价于子网掩码
255.255.255.0
再比如10.0.0.0/8:
8表示前8位是网络位- 等价于子网掩码
255.0.0.0
CIDR的好处是可以表示任意大小的网络块,不局限于传统的A/B/C类。例如192.168.0.0/23表示一个包含512个地址的网络块,跨越了传统C类的边界。
公网IP与私网IP
并不是所有IP地址都能在互联网上直接使用。RFC 1918定义了三段私有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 | 中型网络 |
| 192.168.0.0 - 192.168.255.255 | 192.168.0.0/16 | 家庭和小型办公网络 |
私有IP地址不能在公网上路由。当你用192.168.1.100访问互联网时,路由器会通过NAT(网络地址转换)把它转换成公网IP。
NAT的基本原理
NAT让多台设备共享一个公网IP。过程大致是:
- 内网设备(如
192.168.1.100)发送数据包到互联网 - 路由器将源地址替换为公网IP,同时记录端口映射
- 收到回复后,根据端口映射将数据转发回内网设备
这就是为什么你家可能有好几台设备上网,但运营商只分配了一个公网IP。
特殊IP地址
有些IP地址有特殊用途:
127.0.0.0/8 —— 回环地址
127.0.0.1是最常用的回环地址,也叫localhost- 发送到这个地址的数据包不会离开本机,直接返回
- 常用于本地测试
0.0.0.0 —— 任意地址
- 在服务器配置中表示"监听所有网络接口"
- 路由中表示默认路由
255.255.255.255 —— 受限广播地址
- 向本网络内所有设备广播
网络地址与广播地址
每个子网都有两个特殊地址不能分配给设备:
- 网络地址:主机位全为0,如
192.168.1.0/24中的192.168.1.0 - 广播地址:主机位全为1,如
192.168.1.0/24中的192.168.1.255
所以一个/24网络虽然有256个地址,但只有254个可用。
计算可用主机数
公式很简单:
$$可用主机数 = 2^{主机位数} - 2$$减2就是去掉网络地址和广播地址。
以192.168.1.0/24为例:
- 主机位数 = $32 - 24 = 8$
- 可用主机数 = $2^8 - 2 = 254$
子网划分入门
子网划分是把一个大网络切分成多个小网络。核心思想是"借位":从主机位借一些位来作为子网位。
假设有一个192.168.1.0/24网络,想分成4个子网:
- 需要借2位主机位($2^2 = 4$个子网)
- 新的子网掩码变成
/26(24+2=26),即255.255.255.192 - 每个子网有$2^{6}-2=62$个可用地址
四个子网分别是:
192.168.1.0/26:地址范围 192.168.1.1 - 192.168.1.62192.168.1.64/26:地址范围 192.168.1.65 - 192.168.1.126192.168.1.128/26:地址范围 192.168.1.129 - 192.168.1.190192.168.1.192/26:地址范围 192.168.1.193 - 192.168.1.254
默认网关
当设备要访问本网络之外的地址时,需要通过网关转发。默认网关通常配置为子网的第一个或最后一个可用地址。
例如在192.168.1.0/24网络中:
- 默认网关常设为
192.168.1.1或192.168.1.254 - 所有目的地不在本网段的数据包都发给网关
- 网关(通常是路由器)负责转发到其他网络
常见配置示例
在Linux系统中查看IP配置:
ip addr show eth0
# 输出示例:
# inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
静态配置IP地址:
# Ubuntu/Debian (netplan)
network:
ethernets:
eth0:
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
在代码中判断两个IP是否在同一网段:
import ipaddress
def same_network(ip1, ip2, mask):
net1 = ipaddress.ip_network(f"{ip1}/{mask}", strict=False)
net2 = ipaddress.ip_network(f"{ip2}/{mask}", strict=False)
return net1 == net2
print(same_network("192.168.1.100", "192.168.1.200", 24)) # True
print(same_network("192.168.1.100", "192.168.2.100", 24)) # False
总结
IP地址和子网掩码是网络通信的基石。32位的IPv4地址通过点分十进制表示,子网掩码决定了哪些位是网络号、哪些位是主机号。CIDR表示法提供了灵活的网络划分方式,而公私网地址的区分则让有限的IPv4地址能够支撑庞大的互联网。理解这些概念,是深入学习网络协议和系统配置的第一步。
参考资料:
- RFC 791: Internet Protocol (https://datatracker.ietf.org/doc/html/rfc791)
- RFC 1918: Address Allocation for Private Internets (https://datatracker.ietf.org/doc/html/rfc1918)
- Microsoft Learn: TCP/IP addressing and subnetting (https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcpip-addressing-and-subnetting)
- DigitalOcean: Understanding IP Addresses, Subnets, and CIDR Notation (https://www.digitalocean.com/community/tutorials/understanding-ip-addresses-subnets-and-cidr-notation-for-networking)
- Cloudflare: What is a subnet? (https://www.cloudflare.com/learning/network-layer/what-is-a-subnet/)