Linux网络之IP协议

文章目录

网络层的IP协议详解

IP地址的作用

IP地址提供了一种"能力",将数据包从源设备跨越多个网络,路由到目标设备。其核心任务是实现主机到主机的通信,

然而,这种能力本身是质朴且不设保障的。它只负责派送、不负责追踪和管理------数据包可能在中途丢失、可能不按顺序到达、也可能因网络拥堵而被丢弃。例如,当数据途经的路由器意外断电,传输便会无声无息地中断。IP协议对此不作承诺,它只恪守"尽力而为"的交付原则。

因此,互联网的可靠性需要一个更高维度的策略层来兜底 。这正是传输层 的核心价值所在。以TCP协议为例,它建立了一套精密的确认与重传机制:每份数据都必须收到收件回执,一旦超时未确认,便自动重新发送。同时,它还要负责整理顺序、管理流量,确保数据流完整、准确、有序地重组。

这也是为什么我们经常见到 "TCP/IP协议" 成对出现的原因。

总结来说:

网络层(IP协议) 提供寻址和路由的能力,负责"送到"。

传输层(TCP协议) 提供可靠传输的策略,负责"确保送到"。

补充知识

路由:在复杂的网络结构中,为数据包选出一条从源到目的的可行路径。

主机:配有IP地址,但是不进行路由控制的设备

路由器:即配有IP地址,又能进行路由控制

节点:主机和路由器的统称

IP协议报头

基本格式

  1. 版本:标识IP协议版本,让接收设备知道如何解析这个数据包。IPv4值为4,IPv6值为6

  2. 头部长度 :IP报头可能有可选的"选项"字段,长度可变,因此指定IP报头的长度,以4字节 为单位,取值范围为5-15(对应20-60字节)

  3. 服务类型 :用于指示数据包的优先级或服务质量需求,现代网络主要用作DSCP(区分服务,前6位,用于流量分类)和ECN(显式拥塞通知,后2位,用于拥塞预警)。

  4. 总长度 :定义整个IP数据报的长度,单位为字节,最大值为65535字节(实际受MTU限制)

  5. 标识符 :唯一标识一个IP数据报,用于分片重组,源主机发送数据报时设置一个标识符,所有分片都携带此标识符

  6. 三个标志位:按照顺序,分别为保留位,DF,MF

    • 保留位:必须为0

    • DF:禁止分片标志位。当数据包较长需要分片时,如果DF=1时,那么直接丢弃数据包并返回ICMP错误

    • MF:更多分片标志位。为1表示 后面还有分片,为0表示这是最后一个分片或未分片

  7. 分片偏移 :指示当前分片在原始数据报中的位置,以8字节为单位,接收方按偏移量排序分片

  8. 生存时间 :一个计数器,每经过一个路由器减1,到0时被丢弃,防止数据包在网络中无限循环。Windows默认128,Linux默认64

  9. 协议:标识上层协议类型,告诉接收设备将数据交给哪个协议栈处理(分用)

常见值

  • 1 = ICMP(网络诊断和控制)
  • 6 = TCP(可靠传输)
  • 17 = UDP(无连接传输)
  • 89 = OSPF(路由协议)
  1. 头部校验和 :检测IP报头在传输中的错误

  2. 源IP地址:发送方的IP地址

  3. 目标IP地址:接收方的IP地址

  4. 选项 - 可选字段 :特殊情况下所加的信息,可变,最多40字节。现代很少使用,因为会降低路由器处理速度,不够4字节的填充至4字节,确保报头长度为4的整数倍。

常见选项

  • 记录路由:每个路由器添加自己的IP(用于跟踪)
  • 时间戳:每个路由器添加处理时间戳
  • 松散/严格源路由:指定必须经过的路由器

如何解包和分用

解包:将数据包中的报头信息去除,提取有效载荷。

分用:正确交付给上层。比如传输层分用就是将TCP数据包正确交给上层正确的进程。

网络层的IP协议,在收到IP数据包的时候,根据首部长度来去除头部信息。报文总长度减去首部长度为有效载荷长度,可以轻松解包。

再根据8位协议,将有效载荷交给上层正确的协议栈(TCP/UDP等),这是分用。

IP报头属于自描述字段(自己描述长度属性),IP报文即有头部长度,也有数据长度,可以算出来各个部分的长度

网段划分

IP地址是由2部分构成:IP地址 = 网络号 + 主机号

网络号: 保证相互连接的两个网段具有不同的标识;

主机号: 同一网段内, 主机之间具有相同的网络号, 但是必须有不同的主机号

为什么要进行网段划分呢?

ip是有用且有限的资源,经过合理划分,给不同的区域,国家,组织,学校等。我们的网络世界,也是被精心设计过的,从硬件到软件。

经过精心的设计,合理的划分,可以高效支持未来的报文路径查找,大大提高查找目标主机的效率(在发送方,发送的时候一下可以排除自己所在的整个子网,交给路由器,路由器也按照网络号进行排除子网,也就是一下排除多个主机,而非不划分一个一个去遍历查找)

除此之外,网段划分在以下3个方面也有重要作用

  1. 安全与故障隔离:路由器是天然的防火墙。划分网段后,可以轻松设置规则(如ACL),控制不同部门间的访问权限,并将网络问题(如广播风暴、病毒)限制在单个子网内。
  2. 精心设计的子网划分:根据实际需求(如一个部门50人)分配合适大小的子网,避免浪费为数不多的IP地址,实现精细化管理。
  3. 现实中的需要:网络逻辑应反映现实。按办公楼、部门或功能区(如服务器、Wi-Fi)划分子网,极大简化了运维管理和故障定位。

一句话总结:网段划分通过将大型网络"化整为零"(就像分治一样),同时实现了路由高效、管理清晰、控制安全三大目标。

路由器:具有路由,构建子网等功能

分类划分法

​ 将IP地址分为5类,进行划分

如上图所示,第一个0出现在第1个比特位就是A类,出现在第二个比特位就是2类,以此类推。

地址类别 固定最高位 地址范围(十进制) 网络数 / 主机数 主要用途
A 类 0 1.0.0.0 到 126.0.0.0 126个网络 / 每个约1677万台主机 早期分配给大型国家或巨型机构
B 类 10 128.0.0.0 到 191.255.0.0 16384个网络 / 每个65534台主机 分配给大型企业、高校等
C 类 110 192.0.0.0 到 223.255.255.0 约209万个网络 / 每个254台主机 分配给中小型组织
D 类 1110 224.0.0.0 到 239.255.255.255 不标识网络,用于组播(一对多通信) 组播地址(如OSPF:224.0.0.5)
E 类 1111 240.0.0.0 到 255.255.255.255 保留,仅供实验研究 保留地址

组织或机构在申请IP地址的时候,会分配一个网络

这种设计有致命的不灵活性,导致了IP地址的严重浪费:

  • A类地址:一个网络中的主机数太多,网络数量少,组织或机构申请该类IP困难,并且浪费多,因此大多数都去申请B类,导致A类大量浪费

  • B类地址:一个组织需要1.5万台主机,A类太大(1600万),C类太小(254)。只能申请一个B类地址(6.5万台),导致近5万个地址被闲置。

  • C类地址:小网络太多,C类网络数量迅速枯竭。

这是分类划分话,会存在IP地址大量浪费的情况

CIDR划分法

针对分类划分法浪费大量IP的情况,后续提出了新的划分方案, 称为CIDR(Classless Interdomain Routing):

CIDR完全抛弃了"类"的概念,其核心是 "网络前缀 + 主机号" ,用斜线记法表示(如192.168.1.0/24)。通过可变长的子网掩码,可以根据实际需求,灵活分配任意大小的网络。

这个网络前缀通常代表前多少位标识网络号,剩余的表示主机号,在计算机中,网络前缀即网段,网络号,使用IP地址与子网掩码相与得到。子网掩码是前N个比特位都为1的32位数据,N为网段的位数。

关键计算

  1. 网络地址计算

网络地址 = IP地址 AND 子网掩码

  1. 主机号

主机号 = IP地址中不属于网络前缀的部分

对于/26:后6位为主机号

对于/22:后10位为主机号

具体计算方法:

主机号 = IP地址 AND (NOT子网掩码)

  1. 特殊的IP地址

将IP地址中的主机地址全部设为0, 就成为了网络号, 代表这个局域网;

将IP地址中的主机地址全部设为1, 就成为了广播地址, 用于给同一个链路中相互连接的所有主机发送数 据包;

127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1

具体示例

示例1:192.168.1.130/26

  • IP地址:192.168.1.130

  • 子网掩码:前26位为1,后6位为0,具体为:11111111.11111111.11111111.11000000 = 255.255.255.192

  • 网络号计算

    IP地址:192.168.1.130 = 11000000.10101000.00000001.10000010

    掩码:255.255.255.192 = 11111111.11111111.11111111.11000000

    IP地址 与 掩码 按位与运算:

    ​ 11000000.10101000.00000001.10000010

    AND 11111111.11111111.11111111.11000000

    ​ = 11000000.10101000.00000001.10000000

    ​ = 192.168.1.128

  • 主机号

    IP地址:192.168.1.130 = 11000000.10101000.00000001.10000010

    掩码:255.255.255.192 = 11111111.11111111.11111111.11000000

    掩码取反:00000000.00000000.00000000.00111111

    IP地址 与 掩码反码 按位与运算:

    ​ 11000000.10101000.00000001.10000010

    AND 00000000.00000000.00000000.00111111

    ​ = 00000000.00000000.00000000.00000010

    ​ = 2

  • 广播地址

    网络地址:11000000.10101000.00000001.10000000

    将主机位全置1:11000000.10101000.00000001.10111111 = 192.168.1.191

  • 可用IP范围

    网络地址+1 到 广播地址-1 即 192.168.1.129 ~ 192.168.1.190

示例2:10.10.0.5/22

  • IP地址:10.10.0.5

  • 子网掩码:前22位为1,后10位为0 ,即11111111.11111111.11111100.00000000 = 255.255.252.0

  • 网络号计算

    IP地址:10.10.0.5 = 00001010.00001010.00000000.00000101

    掩码:255.255.252.0 = 11111111.11111111.11111100.00000000

    IP地址 与 掩码 按位与运算:

    ​ 00001010.00001010.00000000.00000101

    AND 11111111.11111111.11111100.00000000

    ​ = 00001010.00001010.00000000.00000000

    ​ = 10.10.0.0

  • 主机号

    IP地址:10.10.0.5 = 00001010.00001010.00000000.00000101

    掩码:255.255.252.0 = 11111111.11111111.11111100.00000000

    掩码取反:00000000.00000000.00000011.11111111

    IP地址 与 掩码反码 按位与运算:

    ​ 00001010.00001010.00000000.00000101

    AND 00000000.00000000.00000011.11111111

    ​ = 00000000.00000000.00000000.00000101

    ​ = 5

  • 广播地址

    网络地址:00001010.00001010.00000000.00000000

    将主机位全置1:00001010.00001010.00000011.11111111

  • 可用IP范围

    网络地址+1 到 广播地址-1

    10.10.0.1 ~ 10.10.3.254

IP地址数量

IP地址(IPv4)的长度为32位,其理论总量约为43亿个(2^32)。然而,这并非意味着可以支持43亿台设备同时在线,原因如下:

  1. 实际可用地址远少于理论值 :由于协议本身定义了部分地址为特殊用途(如网络地址、广播地址、环回地址等),实际可分配给设备的地址数量大幅减少。
  2. 分配单位是网络接口:TCP/IP协议要求每个网络接口(如电脑网卡、手机Wi-Fi模块)都必须拥有至少一个IP地址。一台拥有多个接口的设备(如服务器、路由器)就需要多个IP,这进一步加剧了地址的消耗。

尽管CIDR通过更灵活的地址分配显著提升了利用率、减少了浪费,但它并未增加IP地址的绝对上限。为了从根本上应对地址枯竭问题,主要采用了以下三种方案:

  • 动态主机配置协议:仅为在线设备临时分配IP地址,设备断开后地址收回并可以分配给其他设备。这极大提高了地址的循环利用率。
  • 网络地址转换技术(NAT技术):这是当前最主要的解决方案。它允许多个设备在内部网络中使用私有地址,并通过一个或少数几个公网IP地址共享上网连接。
  • IPv6协议:这是终极解决方案。IPv6采用128位地址,其地址空间近乎无限,与IPv4互不兼容。尽管是未来方向,但其全面普及仍需时间。

私有IP和公网IP

公网,即公共互联网,是由全球所有可公开访问的网络和设备通过唯一且全球可路由的公有IP地址连接而成的巨型网络。它好比覆盖全球的电话系统,每个公网IP都像是一个独一无二的国际电话号码,确保了地球上任何两台设备都能通过这个地址体系直接寻址和通信,构成了我们通常所说的"互联网"主干。

私网 ,则是使用私有IP地址构建的内部网络,如家庭、企业或校园局域网。这些私有地址无法在公网中路由,但可在不同私网中重复使用。私网设备需通过路由器网关和NAT技术,将内部私有地址转换为公网IP后方可访问外部互联网。这就像公司内部分机系统,内部通话直连,而外线呼叫则需通过总机转换。

如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上 使用任意的IP地址都 可以,但是RFC 1918规定了用于组建局域网的私有IP地址

地址段 CIDR表示 包含的IP地址范围 容量 典型用途
A类大块 10.0.0.0/8 10.0.0.0 - 10.255.255.255 1677万 个地址 大型企业、运营商内部网络、数据中心
B类中块 172.16.0.0/12 172.16.0.0 - 172.31.255.255 104万 个地址 中型企业、校园网、较为复杂的网络
C类小块 192.168.0.0/16 192.168.0.0 - 192.168.255.255 6.5万 个地址 家庭网络、小型办公室、消费级路由器默认设置

包含在这个范围中的, 都成为私有IP, 其余的则称为全局IP(或公网IP);

虽然存在公网,但是我们上网都必须先接入指定的一个内网中,我们所有人都在自己的私网中

私有IP具有以下特性:

  • 私有IP不能出现在公网中

  • 私有IP可以在不同的私网中重复

路由器

具有构建子网和路由转发功能。一个路由器至少应同时连接2个网络。

LAN口IP:路由器自己构建的子网的IP地址,即网络号为子网网络号,主机号为0的IP地址

WAN口IP:家用路由器对外连接的运行商的路由器,此时家用路由器相当于处于运营商路由器构建的更"高级"的子网中的一个节点。

出入口路由器:运营商的路由器,其构建的内网接我们家用的路由器,其外接公网,所以他的WAN口IP也是一个公网ip,此时他具有公网IP,就可以与一些服务器,或者其他具有公网IP的服务器进行直接通信

任何一台主机都能够判断清楚和自己直连的网络号是多少

认识公网

互联网IP地址的组织与网络构建,是一个从全球到本地、逐层细分与路由聚合的体系化过程。

第一层:全球范围的地址分配

全球互联网地址管理机构(如IANA)并不直接管理所有IP地址,而是将大型的、连续的IP地址段 分配给各大洲的互联网注册管理机构或主要经济体。每个获得地址段的实体,都管理着一个庞大的自治系统 。这些系统的核心路由器(通常位于国际互联节点)会运行BGP 等路由协议,相互通告诸如"我负责的网段是 "X.X.X.X/Y"这样的信息。通过持续交换这些路由信息,全球的核心路由器最终各自生成了一张能够反映"哪个网段由谁负责"的全球路由表,这是互联网互联互通的根基。

第二层:国家或大型运营商内部的网络规划

一个国家或大型运营商在获得自己的IP地址段后,会进行内部规划和子网划分。

  1. 省级/区域级划分 :将其持有的IP地址段,进一步划分为更小的子网,分配给下属的省份、区域或业务部门。每个区域都会获得一个规划好的、互不重叠的网段
  2. 构建骨干网络 :在各省或区域之间部署高性能路由器,构建国家或运营商级的骨干网络。各省的路由器会向骨干网宣告:"我连接着本区域的网段(例如 202.1.0.0/16)"。通过内部路由协议(如OSPF、IS-IS)的同步,整个骨干网内的路由器都形成了一张清晰的内部路由表,知晓如何到达每一个下属区域网段。

第三层:接入层的地址分配与网络构建

各省或区域拿到自己的网段后,继续向更下层分配:

  • 城域网/汇聚层:继续划分子网,分配给各个城市,用于构建城市级别的汇聚和接入网络。
  • 最终用户接入 :面对海量的最终用户,公网IP地址通常已无法做到"一户一个"。此时,运营商 会采用以下两种主要方式:
    • 分配公网子网:为大型企业、数据中心等直接分配一个公网子网。
    • 大规模部署私有网络 :更普遍的做法是,运营商利用 RFC 1918 私有地址 ,构建一个庞大的接入层私有网络 。成千上万的家庭或企业用户被分配私有IP(如 192.168.x.x),并通过运营商网关的NAT技术,共享一个或数个公网IP地址来访问互联网。

数据流的实际路径

当一个主机向一个远程服务器发送数据包时,数据包的的流向如下所示:

  1. 首先,发送的时候判断是否属于发送方所在的网络,若不是,交给路由器
  2. 路由器收到后经过NAT转换,源IP变为运营商的公网IP,进入城域接入网(也可能是更上层的运营商构建的私网,可以继续判断是否在同一个网络,不是就交给缺省路由器,向上交付)。
  3. 到达公网后,根据城域网、省干网、国家骨干网的路由表指引,数据包被逐跳转发至国家级出口。
  4. 最终,依据全球BGP路由表的指引,数据包通过国际互联链路,到达目标服务器所在的自治系统和具体网段。

路由的过程就是这样一跳一跳"问路"的过程

路由过程:

目标网络在子网中,那么直接内网转发

查完路由表,不在网络中,交给缺省路由器(向上交付)

直到一个路由器的路由表中存在该目标网络

之后向下转发,达到目标网络

IP数据包的分片与组装

数据链路层发送的帧有最大长度限制(MTU)。如果网络层(IP层)要发送的数据报总长度超过了该MTU,IP协议就必须对其进行分片 ,分成多个能在链路层传输的小数据报。接收方的IP层负责将这些分片重组成原始数据报,再交给上层。

因此,对于上层的传输层(如TCP)而言,它交给网络层的数据,最终会被完整地送达对端的传输层。中间的IP分片和重组过程是透明的。

但是,IP分片会降低可靠性 。因为IP协议本身不可靠,如果任何一个分片在传输中丢失,整个原始数据报就无法完成重组,会被接收方丢弃。对于使用TCP的通信,这会导致TCP触发超时重传,重传整个TCP段(而非仅丢失的分片)。过多的分片会显著增加整体丢包的概率。

为了高效且可靠地传输,TCP在传输层就主动将数据分割成合适的大小 。通过最大报文段长度(MSS) 协商机制,TCP会确保每一个TCP段在加上TCP头和IP头后,其总长度不超过路径的MTU。这样就从根本上避免了IP层的分片,减少了因分片丢失导致整个数据报重传的概率,从而提升了传输效率和可靠性。

在网络世界里只有IP数据包。只有双方主机才能意识到使用的是TCP还是UDP协议。

如何分片:

如果传输层的数据加网络层报头(IP报头)后,整体长度大于MTU,那么就需要进行分片。一般来说一个MTU是1500字节。

只需将原IP报文分成几个不超过1500字节的报文分片即可,并且每个分片需要有IP报头,并且设置标识16位标识,3位标志,和13位片偏移等字段。

16位标识用于判断是否属于同一数据包,一个数据包的所有分片中,16位标识相同。

3位标志位中,若是最后一个分片,则更多分片标志位设为0,若不是最后一个分盘,更多分片标志位为1

13位偏移:该分片中有效载荷在原有效载荷中的偏移量,以8字节为单位。

为什么是8字节呢?

报头中具有16为报文长度,也就是说报文的最大长度是216字节,那么在分片的时候,有可能最后一个分片的偏移量就靠近216,此时,13位偏移量已无法表示,那么可以将实际偏移量右移3位,即除以8,这样可以用13位存储最大偏移量。接收方接收到只需左移三位即可,即乘以8。因此一个分片中的有效载荷长度也必须是8的整数倍(最后一个除外)

举个例子:

IP层具有一个3000字节的IP数据包(包括报头),此时就需要对其进行分片

如上图所示,每一个分片的长度都不超过1500字节,每一个分片的报头标识都为2234,标识其来自同一个数据包

  • 第一个分片的更多分片为1,因为其后面还有2,3号分片。偏移量为0,因为他的第一个字节在原始有效载荷中的偏移量为0
  • 第二个分片的更多分片为1,因为其后面还有3号分片。偏移量为185,因为他的第一个字节在原始有效载荷中的偏移量为1480,除以8为185。
  • 第三个分片的更多分片为0,因为其后在无分片。偏移量为270,因为他的第一个字节在原始有效载荷中的偏移量为2960,除以8为270

如何组装:

  1. 如何区分收到的报文是否是分片了的?

收到的ip报文只有3种情况,第一片(偏移量为0),中间片(更多分片标志位为1),最后一片(更多分片标志位为0)

如果偏移量为0且标志位为0,那么该报文没分片,第一片就是最后一片,也是一整个报文。否则是分片了的报文。

  1. 如何保证全部收到?

将所有的分片按照片偏移升序排序,如果全部收到了,那么一个分片的偏移量加上分片有效载荷长度就是下一个分片的偏移量,反之没有 全部收到。并且第一个分片的偏移量应为0,最后一个分片的更多分片标志为0.

  1. 如何组装?

在保证全部收到的基础上,将第一个分片的报头保留,将剩余分片的报头去除,并且有效载荷按照顺序拼接,形成一个完成的IP数据包,与发送方未分片前的数据包相同。

相关推荐
一个平凡而乐于分享的小比特3 小时前
Linux内核中的container_of宏详解
linux·container_of
燃于AC之乐3 小时前
深入解剖STL Vector:从底层原理到核心接口的灵活运用
开发语言·c++·迭代器·stl·vector·源码分析·底层原理
csdn_aspnet9 小时前
TCP/IP协议栈深度解析:从基石到前沿
服务器·网络·tcp/ip
lcreek9 小时前
Linux信号机制详解:阻塞信号集与未决信号集
linux·操作系统·系统编程
优雅的潮叭9 小时前
c++ 学习笔记之 chrono库
c++·笔记·学习
星火开发设计9 小时前
C++ 数组:一维数组的定义、遍历与常见操作
java·开发语言·数据结构·c++·学习·数组·知识
shandianchengzi10 小时前
【记录】Tailscale|部署 Tailscale 到 linux 主机或 Docker 上
linux·运维·docker·tailscale
月挽清风10 小时前
代码随想录第七天:
数据结构·c++·算法