Cx330❀头像
关注
【Linux网络】网络层协议 IP :从网络层原理到 Linux 内核源码封面图

【Linux网络】网络层协议 IP :从网络层原理到 Linux 内核源码

🔥个人主页:Cx330🌸

❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》

《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔

《Git深度解析》:版本管理实战全解 《Qt 极境架构》MySQL 核心技术与实战

🌟心向往之行必能


🎥Cx330🌸的简介:


目录

前言:

一. 预备工作:网络层的基本概念

1.1 网络层的作用

1.2 基本术语定义

1.3 长距离传输的本质

1.4 TCP 与 IP 的关系

1.5 IP 地址的意义

二. IP 地址

2.1 IP 地址的结构

2.2 唐僧取经的例子

三. IP 协议格式

3.2 各字段详细解析

3.2.1 4 位版本号 (Version)

3.2.2 4 位首部长度 (Header Length)

3.2.3 8 位服务类型 (Type Of Service, TOS)

3.2.4 16 位总长度 (Total Length)

3.2.5 16 位标识 (Identification)

3.2.6 3 位标志 (Flags)

3.2.7 13 位片偏移 (Fragment  Offset)

3.2.8 8 位生存时间 (Time To Live, TTL)

3.2.9 8 位协议 (Protocol)

3.2.10 16 位首部检验和 (Header Checksum)

3.2.11 32 位源 IP 地址和目的 IP 地址

3.2.12 选项字段 (Options)

3.2.13 数据部分

四. 源码解读:Linux 内核 IP 头部结构

结尾:


前言:

在现代互联网中,无论我们是在浏览网页、观看视频,还是发送即时消息,底层都离不开网际协议(Internet Protocol,简称 IP 协议)。IP 协议作为 TCP/IP 协议栈中网络层(Network Layer)的核心,承担着在纷繁复杂的网络拓扑中“寻址”和“路由”的重任。

本文将依据网络层的基本原理、IP 地址的逻辑抽象、报文首部格式以及 Linux 内核的源码实现,循序渐进地带大家系统化掌握 IP 协议。


一. 预备工作:网络层的基本概念

1.1 网络层的作用

网络层(也叫互联网层、网际层)的核心作用是在复杂的网络环境中确定一条从源主机到目的主机的合适路径。传输层负责端到端的可靠传输,而网络层负责点到点的路由转发。

1.2 基本术语定义

  • 主机(Host):拥有 IP 地址但不具备路由转发功能(或默认不开启转发)的终点设备。

  • 路由器(Router):拥有多个网络接口(多个 IP 地址),能够根据路由表进行数据包转发的专用设备。

  • IP 数据报(IP Datagram)/ 数据包(Packet):网络层传输的基本数据单位。

  • 跳(Hop):数据包从一个路由器到达下一个路由器的过程。

1.3 长距离传输的本质

长距离网络传输的本质可以概括为:分段转发与路径选择(Routing & Forwarding)

当数据包从源主机出发到达目标主机时,它无法通过一条直接的物理导线直达,而是需要经过沿途许许多多路由器的接力。每个路由器依据数据包中的目的 IP 地址,查询自己的路由表,决定将数据包发往“下一跳(Next Hop)”。

1.4 TCP 与 IP 的关系

很多人常把“TCP/IP”挂在嘴边,但二者分工明确:

  • IP(网络层)是执行者(Action):负责将数据包从源端送到目的端。IP 协议提供的是尽力而为(Best-Effort)的不可靠服务,不保证数据包一定到达,也不保证按序到达。
  • TCP(传输层)是决策者(Strategy):负责可靠性控制、丢包重传、流量控制与拥塞控制。它制定传输策略,但不负责具体的路途运输。

比喻:TCP 就像是公司的项目经理,制定计划和监控进度;IP 则是快递员,只管把包裹送到下一个站点。

两者结合,就提供了把数据从 A 主机可靠地跨网络送到 B 主机的能力

1.5 IP 地址的意义

IP 地址是一个 4 字节(32 位)的数字,它的本质作用是提供一种路由查找的能力,就像我们的学号一样。

通过学号找学生的过程:保安大爷(知道学院)→ 扫地阿姨(知道专业和班级)→ 宿管阿姨(知道宿舍) 通过 IP 地址找主机的过程:路由器 A(知道目标网络)→ 路由器 B(知道下一个子网)→ … → 目标子网的路由器(知道目标主机)

IP 地址之所以能够找到目标主机,是因为它不是一个随机的数字,而是结构化的,包含了目标网络和目标主机两部分信息。


二. IP 地址

2.1 IP 地址的结构

IPv4 地址是一个 32 位的无符号整数,通常采用点分十进制的表示方法(比如192.168.1.1)。它由两部分组成:

  • 网络号:标识主机所在的子网
  • 主机号:标识子网内的具体主机

2.2 唐僧取经的例子

为了更直观地理解 IP 地址与路由选择,我们可以用《西游记》中唐僧取经的故事做类比:

  • 源 IP 地址:东土大唐(长安)。整个取经过程中保持不变

  • 目的 IP 地址:西天大雷音寺。整个取经过程中保持不变

  • 下一跳 / 路由器:沿途经过的各国家与关口(如两界山、高老庄、女儿国等)。

  • MAC 地址:每一段具体路程的起点与终点(例如从长安到界牌关,使用大唐的通关文牒;到了女儿国,使用女儿国的通行证明)。每过一跳,MAC 地址都会改变

当唐僧到达女儿国时,问女儿国国王:“请问去西天怎么走?”国王回答:“下一站去孙陀罗国。”这就是路由决策。唐僧的始发地(源 IP)和目的地(目的 IP)从未改变,但眼下的起点和终点(MAC 地址)在不断切换。


三. IP 协议格式

IP 协议头就像快递单一样,包含了数据传输所需的所有关键信息。理解 IP 协议头的每一个字段,是掌握 IP 协议的关键。

IPv4 协议头的标准长度是 20 字节,如果有选项字段,最长可以达到 60 字节。整体结构如下:

3.2 各字段详细解析

3.2.1 4 位版本号 (Version)

指定 IP 协议的版本,对于 IPv4 来说,这个字段的值是 4;对于 IPv6 来说,这个字段的值是 6。

注意:IPv4 和 IPv6 是两个完全不兼容的协议,IPv6 使用 128 位地址,理论上可以解决 IPv4 地址不足的问题,但目前主流仍然是 IPv4。

3.2.2 4 位首部长度 (Header Length)

指示 IP 报头的大小。单位是 4 字节(32 位 Word)

  • 4 位二进制的最大值为 15。

  • 因此,IP 头的最大长度为 15 * 4 = 60 字节。

  • 标准无选项的 IP 头长度为 20 字节,因此该字段的值通常为 20 / 4 = 5(二进制 0101)。

这个字段的作用是让接收方能够正确地分离 IP 头部和有效载荷:

有效载荷长度 = 总长度 - 首部长度×4
3.2.3 8 位服务类型 (Type Of Service, TOS)

这个字段用于指定 IP 报文的传输优先级和服务质量。它由三部分组成:

  • 3 位优先权字段:已经弃用
  • 4 位 TOS 字段:分别表示最小延时、最大吞吐量、最高可靠性、最小成本
  • 1 位保留字段:必须置为 0

重要特性:这四个 TOS 选项是相互冲突的,只能选择一个。

  • SSH/Telnet 等交互式应用:选择最小延时
  • FTP 等文件传输应用:选择最大吞吐量

不同的服务类型会影响路由器选择的转发路径。

3.2.4 16 位总长度 (Total Length)

表示整个 IP 数据报(头部 + 数据)的总长度,单位是字节。因为是 16 位,所以 IP 数据报的最大长度是 65535 字节。

3.2.5 16 位标识 (Identification)

唯一标识主机发送的每一个 IP 报文。如果 IP 报文在数据链路层被分片了,那么同一个原始报文的所有分片的这个标识字段都是相同的。

接收方通过这个字段来判断哪些分片属于同一个原始报文,从而进行重组。

3.2.6 3 位标志 (Flags)

这个字段用于控制 IP 报文的分片:

  • 第 1 位:保留位,现在不用
  • 第 2 位:禁止分片位 (DF),如果置为 1,表示禁止分片。如果报文长度超过 MTU(最大传输单元),IP 模块会直接丢弃这个报文
  • 第 3 位:更多分片位 (MF),如果置为 1,表示后面还有更多的分片;如果置为 0,表示这是最后一个分片
3.2.7 13 位片偏移 (Fragment  Offset)

表示当前分片相对于原始 IP 报文数据部分的偏移量。实际偏移的字节数是这个值乘以 8

例如:片偏移 = 100,表示这个分片的数据从原始报文的第 800 字节开始。

重要特性:除了最后一个分片之外,其他所有分片的长度都必须是 8 的整数倍,这样才能保证偏移量是整数。

3.2.8 8 位生存时间 (Time To Live, TTL)

表示 IP 报文在网络中能够存活的最大跳数。

  • 初始值一般是 64(不同操作系统可能不同)
  • 每经过一个路由器,TTL 的值减 1
  • 当 TTL 减到 0 时,路由器会丢弃这个报文,并向源主机发送 ICMP 超时错误报文

核心作用防止路由循环。如果网络中出现了路由环路,报文会在环路中无限转发,消耗大量网络资源。TTL 机制保证了报文最终会被丢弃。

我们平时使用的ping命令就可以看到 TTL 的值:

C:\Users\whb>ping www.baidu.com
正在Ping www.a.shifen.com[183.2.172.177]具有32字节的数据:
来自183.2.172.177的回复:字节=32时间=35msTTL=52

这里的 TTL=52 表示这个报文从百度服务器到我们的电脑经过了 64-52=12 个路由器。

3.2.9 8 位协议 (Protocol)

表示 IP 报文的有效载荷是哪种上层协议的数据。接收方通过这个字段来决定将有效载荷交给哪个上层协议处理。

常见的协议号如下:

协议号协议类型全称与说明
1ICMP互联网控制报文协议,用于发送错误报告和网络诊断(如 ping 命令)
2IGMP互联网组管理协议,用于管理 IP 多播组成员
6TCP传输控制协议,提供面向连接的可靠数据传输服务
17UDP用户数据报协议,提供无连接的不可靠数据传输服务
47GRE通用路由封装,用于封装其他网络协议,常被 VPN 使用
50ESP封装安全载荷,IPSec 协议的一部分,用于数据加密和认证
51AH认证头,IPSec 协议的一部分,用于数据完整性校验和身份认证
89OSPF开放最短路径优先,一种内部网关路由协议
3.2.10 16 位首部检验和 (Header Checksum)

用于校验 IP 头部是否在传输过程中损坏。发送方计算 IP 头部的 CRC 校验和并填入这个字段,接收方重新计算校验和,如果和收到的不一致,就丢弃这个报文。

注意:这个校验和只校验 IP 头部,不校验数据部分。数据部分的校验由上层协议(TCP/UDP)负责。

3.2.11 32 位源 IP 地址和目的 IP 地址

分别表示发送方和接收方的 IP 地址,是 IP 报文最重要的字段之一。

3.2.12 选项字段 (Options)

可选字段,最长 40 字节,用于提供一些额外的功能,比如记录路由、时间戳、安全选项等。大多数情况下,这个字段为空。

3.2.13 数据部分

IP 报文的有效载荷,通常是 TCP 段、UDP 数据报或者 ICMP 报文等上层协议的数据。


四. 源码解读:Linux 内核 IP 头部结构

我们来看一下 Linux 内核中 IP 头部的定义(位于include/linux/ip.h):

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u8    ihl:4,      // 首部长度(Internet Header Length)
            version:4;  // 版本号
#elif defined (__BIG_ENDIAN_BITFIELD)
    __u8    version:4,  // 版本号
            ihl:4;      // 首部长度
#else
#error  "Please fix <asm/byteorder.h>"
#endif
    __u8    tos;        // 服务类型(Type Of Service)
    __be16  tot_len;    // 总长度(Total Length)
    __be16  id;         // 标识(Identification)
    __be16  frag_off;   // 标志(3位)+片偏移(13位)
    __u8    ttl;        // 生存时间(Time To Live)
    __u8    protocol;   // 上层协议类型
    __be16  check;      // 首部校验和
    __be32  saddr;      // 源IP地址
    __be32  daddr;      // 目的IP地址
    /* 选项字段从这里开始 */
};

关键字段对应解读

  • version:对应 4 位版本号字段
  • ihl:对应 4 位首部长度字段,单位是 4 字节
  • tos:对应 8 位服务类型字段
  • tot_len:对应 16 位总长度字段
  • id:对应 16 位标识字段
  • frag_off:高 3 位是标志字段,低 13 位是片偏移字段
  • ttl:对应 8 位生存时间字段
  • protocol:对应 8 位协议字段
  • check:对应 16 位首部校验和字段
  • saddr:对应 32 位源 IP 地址字段
  • daddr:对应 32 位目的 IP 地址字段

注意这里的字节序问题:Linux 内核使用了条件编译来处理大端和小端字节序的差异,保证在不同架构的 CPU  上都能正确解析 IP 头部。

核心考点总结

  1. 网络层的核心作用是路由转发,长距离传输的本质是子网间的一跳一跳转发
  2. TCP 与 IP 的关系:IP 提供基础传输能力,TCP 提供端到端的可靠性保障
  3. IP 地址的结构化设计:网络号用于跨子网路由,主机号用于子网内寻址
  4. IP 协议头各字段的作用,特别是 TTL、协议号、首部长度和分片相关字段
  5. TTL 的核心作用是防止路由循环,每经过一个路由器值减 1
  6. 8 位协议字段的常见值(TCP=6,UDP=17,ICMP=1)
  7. IP 分片机制的原理:标识、标志、片偏移三个字段的协同工作

结尾:

IP 协议作为互联网的基石,以简明高效的不可靠数据报服务,支撑起了庞大的全球网络。通过本文对网络层概念、IP 寻址逻辑、报文字段格式以及 Linux 内核代码实现的拆解,我们可以清晰地看到 IP 协议在设计上的巧妙平衡:

  • 简单高效:尽力而为的服务模型,让路由器可以快速转发,无需维护复杂的连接状态;

  • 分层解耦:与上层 TCP/UDP 及底层数据链路层高度解耦,具备极强的适配性与扩展性。

搞懂 IP 协议的原理,是深入学习计算机网络、网络编程以及系统性能调优的必经之路。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/yhrxh_ymq/article/details/164370199

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--