第8天:IP地址详解
“IP地址就像互联网上的门牌号。”
📚 今日目标
- 深入理解IP地址的概念和作用
- 掌握IPv4地址的格式和表示
- 理解IP地址的分类(A/B/C/D/E类)
- 区分公网IP和私网IP
- 编写IP地址分析工具
🎯 什么是IP地址?
生活中的例子
IP地址 = 家庭住址
北京市朝阳区xx街道xx号 → 详细地址
192.168.1.100 → IP地址
作用:
- 唯一标识网络中的设备
- 让数据包找到目的地
- 实现跨网络通信
IP地址(Internet Protocol Address)是分配给网络设备的数字标识,用于在网络中定位和识别设备。
IP地址的两个版本
| 版本 | 全称 | 地址长度 | 地址数量 | 例子 |
|---|---|---|---|---|
| IPv4 | Internet Protocol version 4 | 32位 | 约43亿个 | 192.168.1.1 |
| IPv6 | Internet Protocol version 6 | 128位 | 约340万亿亿亿个 | 2001:0db8::1 |
本节重点:IPv4(最常用)
📊 IPv4地址格式
二进制和十进制表示
IPv4地址是32位二进制数,分成4组,每组8位(1字节):
二进制表示(32位):
11000000.10101000.00000001.00000001
转换为十进制(点分十进制):
192.168.1.1
每组范围:0-255(2^8 = 256)
转换示例
192.168.1.1 的转换过程:
192 = 11000000 (128+64 = 192)
168 = 10101000 (128+32+8 = 168)
1 = 00000001 (1)
1 = 00000001 (1)
完整二进制:
11000000 10101000 00000001 00000001
地址范围
最小IP地址:0.0.0.0
最大IP地址:255.255.255.255
总数:2^32 = 4,294,967,296 个(约43亿)
🏷️ IP地址分类
IPv4地址分为5类:A、B、C、D、E类
A类地址
格式:0xxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
[网络号].[ 主机号(24位) ]
范围:1.0.0.0 - 126.255.255.255
网络数:126个(2^7 - 2,去掉0和127)
每个网络的主机数:16,777,214个(2^24 - 2)
用途:大型网络(如大型企业、ISP)
例子:10.0.0.0(私网)
B类地址
格式:10xxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
[ 网络号(16位) ].[主机号(16位)]
范围:128.0.0.0 - 191.255.255.255
网络数:16,384个(2^14)
每个网络的主机数:65,534个(2^16 - 2)
用途:中型网络(如大学、中型企业)
例子:172.16.0.0(私网)
C类地址
格式:110xxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
[ 网络号(24位) ].[主机号]
范围:192.0.0.0 - 223.255.255.255
网络数:2,097,152个(2^21)
每个网络的主机数:254个(2^8 - 2)
用途:小型网络(如家庭、小型办公室)
例子:192.168.1.0(私网)
D类地址(组播)
格式:1110xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
范围:224.0.0.0 - 239.255.255.255
用途:组播(多播)地址
一对多的通信
例子:224.0.0.1(所有主机组)
E类地址(保留)
格式:1111xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
范围:240.0.0.0 - 255.255.255.255
用途:保留用于将来或实验
分类总结
| 类别 | 首字节范围 | 网络数 | 主机数/网络 | 用途 |
|---|---|---|---|---|
| A | 1-126 | 126 | 16,777,214 | 大型网络 |
| B | 128-191 | 16,384 | 65,534 | 中型网络 |
| C | 192-223 | 2,097,152 | 254 | 小型网络 |
| D | 224-239 | - | - | 组播 |
| E | 240-255 | - | - | 保留 |
🌐 公网IP vs 私网IP
公网IP(Public IP)
定义:可以在互联网上直接访问的IP地址
特点:
- 全球唯一
- 可以从互联网任何地方访问
- 需要向ISP申请
- 数量有限,需要付费
例子:
- 8.8.8.8(Google DNS)
- 114.114.114.114(国内DNS)
- 220.181.38.148(百度)
私网IP(Private IP)
定义:只能在局域网内使用的IP地址
特点:
- 不能在互联网上直接访问
- 可以重复使用(不同局域网可以用相同的私网IP)
- 免费使用
- 需要通过NAT访问互联网
私网IP地址范围(RFC 1918):
A类:10.0.0.0 - 10.255.255.255 (10.0.0.0/8)
B类:172.16.0.0 - 172.31.255.255 (172.16.0.0/12)
C类:192.168.0.0 - 192.168.255.255 (192.168.0.0/16)
对比
| 特性 | 公网IP | 私网IP |
|---|---|---|
| 可访问性 | 互联网可访问 | 仅局域网可访问 |
| 唯一性 | 全球唯一 | 可重复使用 |
| 获取方式 | ISP分配 | 自行分配 |
| 费用 | 通常收费 | 免费 |
| 数量 | 有限 | 充足 |
NAT(网络地址转换)
家庭网络示例:
互联网(公网IP:123.45.67.89)
|
路由器(NAT设备)
|
局域网(私网IP)
|-- 电脑1: 192.168.1.100
|-- 电脑2: 192.168.1.101
|-- 手机: 192.168.1.102
NAT的作用:
将局域网的私网IP转换为公网IP,
使私网设备可以访问互联网。
🔍 特殊IP地址
1. 环回地址(Loopback)
地址:127.0.0.0 - 127.255.255.255
常用:127.0.0.1
作用:本机测试,数据不会发送到网络
别名:localhost
用途:
- 测试网络程序
- 本地开发
- 诊断TCP/IP协议栈
2. 网络地址
定义:主机号全为0的地址
例子:192.168.1.0
作用:表示整个网络,不能分配给主机
3. 广播地址
定义:主机号全为1的地址
例子:192.168.1.255
作用:向网络中所有主机发送数据
4. 默认路由
地址:0.0.0.0
作用:
- 表示"任意地址"
- 路由表中的默认路由
- 服务器监听所有网络接口
5. 受限广播地址
地址:255.255.255.255
作用:向本地网络广播,不会被路由器转发
🔧 实战项目:IP地址分析工具
让我们编写一个IP地址分析工具,实现各种IP地址相关功能!
代码实现
# day08_ip_analyzer.py
# 功能:IP地址分析工具
import socket
import struct
import re
class IPAnalyzer:
"""IP地址分析器"""
def __init__(self):
# 私网IP地址范围
self.private_ranges = [
('10.0.0.0', '10.255.255.255'),
('172.16.0.0', '172.31.255.255'),
('192.168.0.0', '192.168.255.255')
]
def ip_to_int(self, ip):
"""
将IP地址转换为整数
参数:
ip: IP地址字符串(如 "192.168.1.1")
返回:
整数形式的IP
工作原理:
192.168.1.1 = 192*256^3 + 168*256^2 + 1*256 + 1
"""
parts = ip.split('.')
return (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
(int(parts[2]) << 8) + int(parts[3])
def int_to_ip(self, num):
"""
将整数转换为IP地址
参数:
num: 整数形式的IP
返回:
IP地址字符串
"""
return f"{(num >> 24) & 255}.{(num >> 16) & 255}." \
f"{(num >> 8) & 255}.{num & 255}"
def ip_to_binary(self, ip):
"""
将IP地址转换为二进制表示
参数:
ip: IP地址字符串
返回:
二进制字符串(用点分隔)
"""
parts = ip.split('.')
binary_parts = [format(int(part), '08b') for part in parts]
return '.'.join(binary_parts)
def validate_ip(self, ip):
"""
验证IP地址格式是否正确
参数:
ip: IP地址字符串
返回:
True/False
"""
pattern = r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$'
match = re.match(pattern, ip)
if not match:
return False
# 检查每个数字是否在0-255范围内
for num in match.groups():
if int(num) > 255:
return False
return True
def get_ip_class(self, ip):
"""
判断IP地址的类别(A/B/C/D/E类)
参数:
ip: IP地址字符串
返回:
类别字符串和详细信息
"""
first_octet = int(ip.split('.')[0])
if 1 <= first_octet <= 126:
return 'A', '大型网络', '1-126'
elif 128 <= first_octet <= 191:
return 'B', '中型网络', '128-191'
elif 192 <= first_octet <= 223:
return 'C', '小型网络', '192-223'
elif 224 <= first_octet <= 239:
return 'D', '组播地址', '224-239'
elif 240 <= first_octet <= 255:
return 'E', '保留地址', '240-255'
else:
return '未知', '特殊地址', '0或127'
def is_private_ip(self, ip):
"""
判断是否为私网IP
参数:
ip: IP地址字符串
返回:
True/False
"""
ip_int = self.ip_to_int(ip)
for start, end in self.private_ranges:
start_int = self.ip_to_int(start)
end_int = self.ip_to_int(end)
if start_int <= ip_int <= end_int:
return True
return False
def is_special_ip(self, ip):
"""
判断是否为特殊IP地址
参数:
ip: IP地址字符串
返回:
(是否特殊, 类型说明)
"""
# 环回地址
if ip.startswith('127.'):
return True, '环回地址(Loopback)'
# 默认路由
if ip == '0.0.0.0':
return True, '默认路由/任意地址'
# 受限广播
if ip == '255.255.255.255':
return True, '受限广播地址'
# 网络地址(主机号全0)
if ip.endswith('.0'):
return True, '网络地址'
# 广播地址(主机号全255)
if ip.endswith('.255'):
return True, '广播地址'
return False, ''
def analyze(self, ip):
"""
全面分析IP地址
参数:
ip: IP地址字符串
返回:
分析结果字典
"""
if not self.validate_ip(ip):
return {'valid': False, 'error': 'IP地址格式不正确'}
result = {
'valid': True,
'ip': ip,
'binary': self.ip_to_binary(ip),
'integer': self.ip_to_int(ip),
'class': self.get_ip_class(ip),
'is_private': self.is_private_ip(ip),
'is_public': not self.is_private_ip(ip) and not self.is_special_ip(ip)[0],
'special': self.is_special_ip(ip)
}
return result
def print_analysis(self, ip):
"""
打印IP地址分析结果
参数:
ip: IP地址字符串
"""
print("=" * 70)
print("IP地址分析结果".center(70))
print("=" * 70)
result = self.analyze(ip)
if not result['valid']:
print(f"\n❌ {result['error']}")
return
print(f"\n📍 IP地址: {result['ip']}")
print(f"🔢 十进制: {result['integer']}")
print(f"💾 二进制: {result['binary']}")
ip_class, usage, range_str = result['class']
print(f"\n📊 地址类别: {ip_class}类")
print(f" 用途: {usage}")
print(f" 范围: {range_str}")
print(f"\n🌐 地址类型:")
if result['special'][0]:
print(f" ⭐ {result['special'][1]}")
elif result['is_private']:
print(f" 🏠 私网IP(不能在互联网上直接访问)")
else:
print(f" 🌍 公网IP(可以在互联网上直接访问)")
print("\n" + "=" * 70)
def get_local_ips():
"""
获取本机所有IP地址
返回:
IP地址列表
"""
try:
# 获取主机名
hostname = socket.gethostname()
# 获取所有IP
ips = socket.gethostbyname_ex(hostname)[2]
return ips
except:
return []
def main():
"""
主函数
"""
analyzer = IPAnalyzer()
print("=" * 70)
print("IP地址分析工具".center(70))
print("=" * 70)
# 显示本机IP
local_ips = get_local_ips()
if local_ips:
print("\n💻 本机IP地址:")
for ip in local_ips:
print(f" {ip}")
print("\n" + "-" * 70)
while True:
print("\n请选择操作:")
print("1. 分析IP地址")
print("2. IP地址转换(十进制 ↔ 二进制)")
print("3. 批量分析")
print("0. 退出")
choice = input("\n请输入选项: ").strip()
if choice == '0':
print("\n再见!")
break
elif choice == '1':
ip = input("\n请输入IP地址: ").strip()
if ip:
analyzer.print_analysis(ip)
elif choice == '2':
ip = input("\n请输入IP地址: ").strip()
if ip and analyzer.validate_ip(ip):
print(f"\n十进制: {ip}")
print(f"二进制: {analyzer.ip_to_binary(ip)}")
print(f"整数: {analyzer.ip_to_int(ip)}")
elif choice == '3':
print("\n请输入多个IP地址(每行一个,输入空行结束):")
ips = []
while True:
ip = input().strip()
if not ip:
break
ips.append(ip)
print(f"\n{'IP地址':<18} {'类别':<8} {'类型':<15}")
print("-" * 45)
for ip in ips:
result = analyzer.analyze(ip)
if result['valid']:
ip_class = result['class'][0]
if result['special'][0]:
ip_type = result['special'][1][:12]
elif result['is_private']:
ip_type = '私网'
else:
ip_type = '公网'
print(f"{ip:<18} {ip_class:<8} {ip_type:<15}")
if __name__ == "__main__":
main()
运行程序
python code/day08/day08_ip_analyzer.py
🎓 知识小结
今天我们学习了:
- ✅ IP地址是32位二进制数(IPv4)
- ✅ IP地址分为5类:A/B/C/D/E
- ✅ 私网IP不能在互联网上直接使用
- ✅ 特殊IP地址有特定用途
- ✅ 能够分析和转换IP地址
💪 练习题
判断以下IP地址的类别和类型:
- 10.0.0.1
- 172.20.1.1
- 202.96.209.133
- 127.0.0.1
将以下IP转换为二进制:
- 192.168.1.1
- 255.255.255.0
计算:A类地址的网络数和每个网络的主机数
💡 今日金句:IP地址是互联网的基石!
👉 上一天:Wireshark抓包 | 返回目录 | 下一天:子网划分实战