IP协议详解:从基础到应用
IP协议基础概念
IP协议位于TCP/IP模型的网络层,主要负责实现主机之间的通信,也称为端到端通信。
网络层与数据链路层的关系
IP协议负责在非直连的网络之间进行通信传输,而MAC地址则实现直连设备之间的通信。这种分层结构确保了数据能够正确地从源主机到达目标主机。
在数据传输过程中,源IP地址和目标IP地址保持不变(未使用NAT的情况下),而源MAC地址和目标MAC地址则会在每个网络跳点发生变化。
IP地址分类
早期互联网设计时,IP地址被分为5类:A类、B类、C类、D类和E类。
- A类地址:首位为0,网络号占8位,主机号占24位
- B类地址:前两位为10,网络号占16位,主机号占16位
- C类地址:前三位为110,网络号占24位,主机号占8位
- D类地址:前四位为1110,用于多播
- E类地址:前四位为1111,保留地址
主机数量计算
每类地址的最大主机数计算方式为2的主机号位数次方减2。减去2是因为主机号全为0和全为1的地址有特殊用途:
- 主机号全为0:表示网络本身
- 主机号全为1:表示该网络的广播地址
例如,C类地址的主机号占8位,所以最大主机数为28-2=254。
广播与多播
广播地址用于在同一链路中向所有主机发送数据包。例如,172.20.0.0/16网络的广播地址是172.20.255.255。
多播则用于将数据包发送给特定组内的所有主机。多播使用D类地址(224.0.0.0至239.255.255.255),可以穿透路由器,适用于跨网络的组通信。
无分类地址CIDR
由于分类地址存在灵活性不足、与现实网络不匹配等问题,后来提出了无分类地址方案,即CIDR(Classless Inter-Domain Routing)。
CIDR使用a.b.c.d/x的形式表示,其中/x指明前x位为网络号,剩余位为主机号。例如,10.100.122.2/24表示前24位是网络号,后8位是主机号。
另一种划分方式是使用子网掩码。子网掩码与IP地址进行按位与运算,可以得到网络号。例如:
IP地址: 192.168.1.100
子网掩码: 255.255.255.0
网络号: 192.168.1.0
子网划分
子网划分是将主机地址进一步分为子网网络地址和子网主机地址。未划分子网的IP地址结构为:网络地址+主机地址;划分子网后变为:网络地址+(子网网络地址+子网主机地址)。
公有IP与私有IP
IP地址分为公有IP和私有IP:
- 私有IP地址:在内部网络中使用,可重复使用,由内部IT人员管理分配
- 公有IP地址:全球唯一,由ICANN及其下属机构统一分配管理
常用的私有IP地址范围:
- A类:10.0.0.0 - 10.255.255.255
- B类:172.16.0.0 - 172.31.255.255
- C类:192.168.0.0 - 192.168.255.255
IP地址与路由控制
IP地址的网络部分用于路由控制。路由器根据目标IP地址的网络部分,在路由表中查找对应的下一跳地址。如果存在多个匹配项,则选择最长匹配(即网络前缀最长的项)。
环回地址
环回地址(127.0.0.1)用于同一台计算机上的程序之间进行网络通信。使用该地址时,数据包不会流向网络,而是在本地处理。
IP分片与重组
每种数据链路都有最大传输单元(MTU)。当IP数据包大小超过MTU时,需要进行分片。分片后的IP数据报只能由目标主机进行重组,路由器不会进行重组。
由于分片传输中一旦某个分片丢失会导致整个IP数据报作废,TCP引入了MSS(最大分段大小)机制,在传输层进行分片,避免在网络层分片。
IPv4与IPv6首部
IPv4首部长度可变,最小20字节,包含版本、首部长度、服务类型、总长度、标识、标志、片偏移、TTL、协议、首部校验和、源IP地址和目标IP地址等字段。
IPv6首部固定为40字节,简化了结构,去除了校验和、分片等相关字段,将分片功能交由扩展头处理。
IP相关协议
DNS域名解析
DNS(Domain Name System)将域名转换为IP地址,使得用户可以使用易于记忆的域名而非IP地址访问网络资源。
ARP协议
ARP(Address Resolution Protocol)用于通过已知的IP地址查找对应的MAC地址。ARP通过广播ARP请求包,拥有目标IP地址的设备会返回ARP响应包,包含其MAC地址。
// ARP请求过程示例
function sendARPRequest(targetIP) {
// 构造ARP请求包
let arpPacket = {
senderIP: myIP,
senderMAC: myMAC,
targetIP: targetIP,
targetMAC: "00:00:00:00:00:00", // 未知
opcode: "REQUEST"
};
// 广播发送ARP请求
broadcast(arpPacket);
}
// 收到ARP请求时的处理
function handleARPRequest(arpPacket) {
if (arpPacket.targetIP === myIP) {
// 构造ARP响应包
let arpResponse = {
senderIP: myIP,
senderMAC: myMAC,
targetIP: arpPacket.senderIP,
targetMAC: arpPacket.senderMAC,
opcode: "REPLY"
};
// 发送ARP响应
sendTo(arpResponse, arpPacket.senderMAC);
}
}
RARP协议
RARP(Reverse Address Resolution Protocol)与ARP相反,用于通过已知的MAC地址查找对应的IP地址。常用于无盘工作站等设备获取IP地址。
DHCP协议
DHCP(Dynamic Host Configuration Protocol)用于自动分配IP地址、子网掩码、默认网关等网络配置信息。DHCP通过四个步骤完成地址分配:
- 客户端发送DHCP发现报文(DHCP DISCOVER)
- 服务器响应DHCP提供报文(DHCP OFFER)
- 客户端发送DHCP请求报文(DHCP REQUEST)
- 服务器发送DHCP确认报文(DHCP ACK)
DHCP客户端使用UDP端口68,服务器使用UDP端口67。整个过程使用广播通信。
对于跨网络的DHCP服务,可以使用DHCP中继代理。DHCP中继代理将客户端的广播包转换为单播包发送给DHCP服务器,再将服务器的响应广播给客户端。
NAT协议
NAT(Network Address Translation)用于缓解IPv4地址短缺问题,将私有IP地址转换为公有IP地址。NAPT(Network Address and Port Translation)更进一步,通过转换IP地址和端口号,使多个内部设备可以共享一个公有IP地址。
// NAPT转换表示例
function naptTranslation(internalPacket) {
// 查找或创建转换表项
let mapping = findOrCreateMapping(
internalPacket.sourceIP,
internalPacket.sourcePort
);
// 转换数据包
let externalPacket = {
sourceIP: publicIP,
sourcePort: mapping.externalPort,
destIP: internalPacket.destIP,
destPort: internalPacket.destPort,
data: internalPacket.data
};
// 更新转换表
updateMapping(mapping);
return externalPacket;
}
NAT的缺点包括:外部无法主动与NAT内部服务器建立连接、转换表生成与操作产生性能开销、NAT路由器重启会导致所有TCP连接重置。
解决NAT问题的方法包括:改用IPv6(地址空间极大,无需NAT)和使用NAT穿透技术(应用程序主动发现NAT设备并建立端口映射)。
ICMP协议
ICMP(Internet Control Message Protocol)用于在IP网络中发送控制消息,提供有关网络状况的反馈。ICMP主要功能包括:确认IP包是否成功送达目标地址、报告IP包被废弃的原因、改善网络设置等。
ICMP分为两大类:查询报文类型(用于诊断)和差错报文类型(通知出错原因)。
ping命令
ping命令使用ICMP回送请求(类型8)和回送应答(类型0)消息测试网络连通性。ping发送ICMP回送请求消息,目标主机收到后返回ICMP回送应答消息。
ping过程包括:
- 构建ICMP回送请求消息(类型8)
- 添加IP首部(协议字段设为1表示ICMP)
- 添加MAC首部
- 发送数据包
- 接收并处理ICMP回送应答消息(类型0)
- 计算往返时间(RTT)
traceroute命令
traceroute(Windows中为tracert)利用ICMP差错报文类型追踪到目的地的路径。它通过发送TTL从1开始递增的UDP包,强制接收ICMP超时消息,从而识别沿途的路由器。
当UDP包到达目标主机时,目标主机会返回"端口不可达"的ICMP消息,表明数据包已到达目的地。
特殊IP地址解析
127.0.0.1与localhost
127.0.0.1是IPv4的环回地址,用于本地主机内部通信。localhost是一个域名,默认解析为127.0.0.1,但可以在hosts文件中修改。
即使断开网络连接,仍然可以ping通127.0.0.1,因为环回地址的数据包不会经过物理网卡,而是在本地处理。系统检测到目标IP是环回地址时,会选择本地网卡(虚拟网卡)处理数据包,数据包被发送到input_pkt_queue链表,然后通过软中断机制返回给应用程序。
0.0.0.0
0.0.0.0在IPv4中表示无效的目标地址,不能用于ping。但在服务器编程中,监听0.0.0.0表示监听本机上的所有IPv4地址。
// 服务器监听示例
// 监听所有IPv4地址
server.listen(80, '0.0.0.0', () => {
console.log('Server listening on all interfaces');
});
// 仅监听本地回环地址
server.listen(80, '127.0.0.1', () => {
console.log('Server listening on localhost only');
});
// 监听特定网络接口
server.listen(80, '192.168.1.100', () => {
console.log('Server listening on specific interface');
});
客户端连接时,必须指定具体的服务器IP地址,不能使用0.0.0.0。