网络层协议:IP

概括

IP(Internet Protocol)是互联网的核心协议之一,负责在网络中寻址和路由数据包。它定义了数据包的格式和传输规则,确保数据能够从源主机到达目标主机。IP协议分为IPv4和IPv6两个主要版本。

报头

学习IP协议前我们也先看看他的报头长什么样:

可以发现其和TCP报头非常的像,难怪说是TCP/IP模型呢。

大家的基本报头大小都是20字节。

我们接下来逐个讲解IP报头的各个属性。

4位版本

4位版本就是对应IP的版本,对于IPv4来说,版本就是4.

4位首部长度

和TCP报头一样,记录报头大小的,基本单位是4字节。报头除掉选项部分就是基本报头,基础大小是20字节,填在4位首部长度就是0b101.最大能填0b1111,即60字节,因此选项最多40字节。

8位服务类型(TOS)

8位服务类型(Type of Service, TOS)是IPv4报文头中的一个字段,用于指定数据包的服务质量(QoS)需求。该字段长度为8位,包含优先级、延迟、吞吐量、可靠性等参数,帮助网络设备对流量进行差异化处理。

TOS字段的8位通常分为以下两部分:

前3位:优先级(Precedence),范围0-7,数值越高优先级越高。

后5位:服务类型标志(DTRC),包括:

  • D(Delay):低延迟(0为正常,1为要求低延迟)。
  • T(Throughput):高吞吐量(0为正常,1为要求高吞吐量)。
  • R(Reliability):高可靠性(0为正常,1为要求高可靠性)。
  • C(Cost):低成本(0为正常,1为要求低成本)。
  • 未使用位:通常置0

常见TOS值示例

  • 默认服务(0x00):00000000,普通路由。
  • 最小延迟(0x10):00010000,适用于实时应用(如VoIP)。
  • 最大吞吐量(0x08):00001000,适用于大文件传输。
  • 最高可靠性(0x04):00000100,适用于关键数据(如金融交易)。

实际应用

  • 差异化服务(DiffServ):现代网络通常将TOS字段重新定义为DSCP(DiffServ Code Point),用于更复杂的QoS策略。
  • 协议支持:某些路由协议(如OSPF)会使用特定TOS值标记控制报文。

我们可以通过iptables指令设置TOS值:

shell 复制代码
iptables -t mangle -A POSTROUTING -p tcp --dport 80 -j TOS --set-tos 0x10

注意事项

  • 兼容性:并非所有网络设备都支持TOS字段处理,需确认设备功能。
  • 替代方案:在IPv6中,类似功能由流量类别(Traffic Class)字段实现。

16位总长度

不同于TCP报头,IP报头会描述自己的报文大小,这个下面讲分片和组装的时候会用到。

8位生存时间(TTL)

TTL(Time To Live)是网络协议中用于限制数据包或记录在系统中存活时间的字段。8位TTL表示该字段占用1字节(8比特),取值范围为0-255。

TTL的作用

  • 防止数据包无限循环:当TTL值减至0时,路由器或设备会丢弃该数据包并返回ICMP超时消息。
  • 控制缓存有效期:在DNS记录中,TTL决定该记录在缓存中的存储时间(以秒为单位)。

TTL的递减机制

每经过一个路由器(跳数),TTL值减1。若TTL为0且未到达目的地,数据包将被丢弃。

那么为什么需要TTL呢,网络世界复杂多变,发生任何故障都是有可能的。像一个数据包有可能在不同路由器之间形成环路:

那如果让这个数据包无限时间生存下去,浪费资源还是一方面。随着时间的积累,所有路由器之间都会堆积很多的这种报文,会导致网络世界瘫痪。因此限制其存活还是非常有必要的。

8位协议

规定要交付的上层协议。

每个协议都要实现:

  1. 有效载荷和报头的分离
  2. 分用

IP协议通过首部长度实现有效载荷分离,通过8位协议实现分用。

16位首部检验和

IP首部的检验和是一个16位的字段,用于确保IP数据报头部在传输过程中未被破坏。

源IP地址、目的IP地址

这个没什么可说的,TCP/IP模型以五元组唯一标识一个通信,其中就包括源IP地址和目的IP地址。

网络基础里,我曾经说过IP地址能唯一标识互联网上一台主机 ,现在我们学习IP之后这个结论要稍作修改:公网IP能唯一标识互联网上的一台主机。

在下文我将阐述公网和私网的区别。

网段划分

在继续讲IP报头和公网、私网概念前,先阐述一下IP世界中一个非常重要的概念:网段划分。

网段划分是指将一个较大的IP地址范围划分为多个较小的子网(Subnet),以提高网络管理的灵活性和效率。通过子网划分,可以优化IP地址分配、减少广播流量并增强安全性。

首先我们要知道IP地址分为两部分:网络号+主机号。

  • 网络号:保证相互连接的两个网段具有不同的标识;
  • 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号

当然不是前四个字节网络号、后四个字节主机号这样,其中有着复杂的划分。

  • 不同的子网其实就是把网络号相同的主机放到一起.
  • 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复.

通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同.

那么问题来了,手动管理子网内的IP,是一个相当麻烦的事情

  • 有一种技术叫做DHCP,能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便.

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一种网络协议,用于自动分配IP地址、子网掩码、默认网关和其他网络配置参数给客户端设备。它简化了网络管理,避免了手动配置IP地址的繁琐和错误。

  • 一般的路由器都带有DHCP功能.因此路由器也可以看做一个DHCP服务器

网段划分的原因

继续讲网段划分方式前,我先说一下为什么要网段划分:

  1. 首先就是IP地址是经过精心设计的,合理的划分,可以高效支持未来的报文路径查找,大大提高目标主机的效率。

举个例子,IP地址就像我们的身份证号,身份证号有18位。不考虑X,就有1018种组合,如果今天需要找到一个身份证号对应的人在什么地方,需要遍历一遍的话就太慢了。好在我们的身份证前六个数字就标记了这个人的户口所在地,比如一个身份证的前六位是441802代表广东省清远市清城区,这样就能将需要遍历的范围变成1012,后续还有出生年月之类的。

这种设计方式在前面讲二级页表的时候也提到过,减少了存储花销。

IP地址也是一样的道理:

如上当主机A向主机B通信时,A所在的子网的网络号是192.168.1。A发送报文里存放着B的IP地址,很容易算出B的网络号不是192.168.1,那么B就和A不在同一个局域网,A就会将报文直接交给路由器。

路由器同时处在两个子网中,一个网络号是192.168,一个网络号是192.168.1这个就是路由器管理的子网。

然后这时候B的网络号就变了,变成了192.168和路由器同在一个子网。同一个子网的主机具有一张路由表能直接找到同一个子网中的其他主机,因此路由器就会将报文传给隔壁路由器,隔壁路由器又会将B的网络号算一遍,这次又变了,变成192.168.2真是他管理的子网,所以他就会将报文直接投给B主机。

这里讲的有点粗犷,下面会逐渐补充完整细节。

接下里是网段划分的第二个原因:

  1. IP是有用且有限的资源,要经过合理的划分,来给不同的区域,国家,组织,学校等。

我们很容易注意到,IP地址是4字节,232。这个数字放在网络刚起步的时候可能是完全够用,但到了今天,他已经不够用了。

现在自然有不同的策略解决IP地址不够用的事情,我们下文再做探讨。

总之IP地址有限,自然要合理划分给不同的人。

不过IP的划分是一件非常复杂的事情,不是简单的按国家、区域划分。下面是我查到的我国运营商的部分ip划分:

运营商 核心公网 IP 段(CIDR / 范围) 覆盖场景 特点
中国电信 114.0.0.0/8(114.0.0.0~114.255.255.255) 全国骨干网、企业专线 覆盖广,稳定性强,多用于政企客户
中国电信 183.0.0.0/8(183.0.0.0~183.255.255.255) 家庭宽带、移动终端 下沉市场覆盖多,用户基数大
中国电信 121.0.0.0/8(121.0.0.0~121.255.255.255) 南方地区为主,兼顾全国 与联通 IP 段互补覆盖
中国电信 218.0.0.0~218.255.255.255 补充网段,覆盖边缘地区 多为后期扩容分配
中国联通 123.0.0.0/8(123.0.0.0~123.255.255.255) 北方地区(京津冀、东北) 北方核心网段,政企客户集中
中国联通 116.0.0.0/8(116.0.0.0~116.255.255.255) 全国覆盖,以东部为主 兼顾家庭与企业用户
中国联通 60.0.0.0~60.63.255.255 补充网段,区域化覆盖 多分布在华东、华南地区
中国移动 211.0.0.0/8(211.0.0.0~211.255.255.255) 4G/5G 基站、移动互联网 移动终端(手机、平板)专用
中国移动 111.0.0.0/8(111.0.0.0~111.255.255.255) 家庭宽带、物联网设备 物联网(IoT)场景占比高
中国移动 103.0.0.0/8(103.0.0.0~103.255.255.255) 全国覆盖,新兴区域补充 后期扩容重点网段
中国移动 223.0.0.0~223.255.255.255 5G 核心网、企业专线 高带宽场景优先分配

网段划分的方式

过去曾经提出一种划分网络号和主机号的方案,把所有IP地址分为五类,如下图所示

  • A类0.0.0.0到127.255.255.255
  • B类128.0.0.0到191.255.255.255
  • C类192.0.0.0到223.255.255.255
  • D类224.0.0.0到239.255.255.255
  • E类240.0.0.0到247.255.255.255

随着Internet的飞速发展,这种划分方案的局限性很快显现出来,大多数组织都申请B类网络地址,导致B类地址很快就分配完了,而A类却浪费了大量地址

因为一个子网通常不会有这么多主机。

因此随着时代的发展,这种划分方案被丢弃,取而代之的是CIDR(ClasslessInterdomainRouting,无类别域间路由):

  • 引入一个额外的子网掩码(subnetmask)来区分网络号和主机号;
  • 子网掩码也是一个32位的正整数.通常用一串"0"来结尾;
  • 将IP地址和子网掩码进行"按位与"操作,得到的结果就是网络号;
  • 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关

例如:

IP地址:140.252.20.68

子网掩码:255.255.255.0

很明显,这个子网掩码的前24位都是1,ip地址和他按位与之后:140.252.20.0就是其网络号,那么其主机号就是0.0.0.68。

上面这个例子比较简单,我们再来:

IP地址:140.252.20.68

子网掩码:255.255.255.240

240对应的二进制就是0b1111 0000,68对应的二进制是0b0100 0100,与240按位与之后就是0b0100 0000,即64,故网络号为:140.252.20.64,主机号是0.0.0.4。

可见,IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围;

IP 地址和子网掩码还有一种更简洁的表示方法,例如140.252.20.68/24,表示IP地址为140.252.20.68, 子网掩码的高24位是1,也就是255.255.255.0

可以看到,CIDR能让IP地址利用更加充分,但仅此而已。这还是没有解决IP地址不够用的窘境。

特殊的IP地址

  • 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网;
  • 将IP地址中的主机地址全部设为1,就成为了广播地址 ,用于给同一个链路中相互连接的所有主机发送数据包;
    广播地址在后面讲数据链路层的时候还会详谈。
  • 127.*的IP地址用于本机环回(loopback)测试,通常是127.0.0.1

IPv6

IPv6(Internet Protocol version 6)是互联网协议的第六版,用于替代IPv4。IPv6的主要目标是解决IPv4地址耗尽问题,提供更大的地址空间(128位地址长度,约3.4×10³⁸个地址),并改进路由效率、安全性(原生支持IPsec)和自动配置功能(如无状态地址自动配置SLAAC)。

IPv6就是解决ipv4地址耗尽的一种方案,但是目前还没完全推广。现在主流的还是ipv4,我们不做详谈。

不过随着时代的发展,ipv6会逐渐取代ipv4.ipv4将成为一代人的眼泪,,你们准备好乘上时代的巨轮了吗?

私有IP地址和公网IP地址

私有IP地址和公网IP地址才是我们主要讲的解决ipv4耗尽的方案。

私有IP地址相当于,每个家庭都有门牌号,这个门牌号是唯一标识的。我们可以给家庭成员安序号,比如老大是1,老二就是2.那么这个序号在自家也是唯一的,但在别人家里可能会重复。

这里门牌号就相当于公网ip,家庭成员序号就是私网ip。

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

  • 10.*,前8位是网络号,共16,777,216个地址
  • 172.16.到172.31.,前12位是网络号,共1,048,576个地址
  • 192.168.*,前16位是网络号,共65,536个地址

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

现在你们如果用cmd输入ipconfig指令查阅自己的ip,那么可以发现大多数读者的ip都是私有ip。

可以看到私有ip在ip世界是会重复的,因此私有ip是不允许出现在广域网通信的,最终会转化成公网ip。

我们来看下图:

前面提到,一个路由器会在两个子网中,现在明确一下:

  • 一个路由器可以配置两个IP地址,一个是WAN口IP,一个是LAN口IP(子网IP).

Local Area Network(局域网)Wide Area Network(广域网)

  • 路由器LAN口连接的主机,都从属于当前这个路由器的子网中.
  • 不同的路由器,子网IP其实都是一样的(通常都是192.168.1.1).子网内的主机IP 地址不能重复.但是子网之间的IP地址就可以重复了.
  • 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点.这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP了

子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN口IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP.这种技术称为NAT(NetworkAddress Translation,网络地址转换)

例如:

当192.168.1.201想向122.77.241.3通信时。

首先192.168.1.201根据自己的子网掩码算出122.77.241.3的网络号为122.77.241.0和自己不在一个子网,就会将数据包交给路由器,路由器会将报文上的源IP地址改成自己的WAN口地址,没错这里就做了一次地址替换。然后路由器根据自己的子网掩码又算出122.77.241.3和自己不在一个网段,就继续将数据包交给上级路由器。上级路由器又将源IP地址改成自己的WAN口地址。最后这个数据包经过广域网交给122.77.241.3,122.77.241.3只会以为自己在和122.77.241.4通信。

如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上.

路由

路由是网络中将数据包从源地址传输到目标地址的过程。路由器根据路由表中的信息决定数据包的转发路径,确保数据能够高效、准确地到达目的地。路由分为静态路由和动态路由两种主要类型。

路由的过程,就是这样一跳一跳(HopbyHop)"问路"的过程.

所谓"一跳"就是数据链路层中的一个区间.具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间.

IP 数据包的传输过程也和问路一样.

  • 当IP数据包,到达路由器时,路由器会先查看目的IP;
  • 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器;
  • 依次反复,一直到达目标IP地址;

那么如何判定当前这个数据包该发送到哪里呢?这个就依靠每个节点内部维护一个路由表;

我们可以用route指令查看自己的路由表:

先明确路由表各列的作用:

  • Destination:目标网络 / 主机(数据包要发往的地址)
  • Gateway:网关(转发数据包的下一跳设备,0.0.0.0表示 "直连网络,无需网关")
  • Genmask:子网掩码(定义目标的网络范围)
  • Flags:路由标志(如U=可用、G=需网关、H=目标是主机)
  • Metric:路由优先级(数值越小优先级越高)
  • Ref:路由引用数(内核使用,通常为 0)
  • Use:路由被使用的次数
  • Iface:出接口(数据包从该网卡发出)

16位标识、3位标志、片偏移

首先我们要知道MTU:

MTU(Maximum Transmission Unit,最大传输单元)

数据链路层(如以太网) 能传输的单个数据包的最大字节数(包含 IP 头、TCP/UDP 头和数据)。

以太网默认 MTU:1500 字节

这意味着,IP层向下交付数据包时,报文(包括报头)不能超过1500字节。如果超过了就要拆开这些报文,也就是分片。分批送到远端再组装。

但是我们的IP可没有可靠性保障,重传机制什么的。一个报文中一个分片丢了,就意味着这个报文丢了。如果是TCP还好,可以重传;但如果是UDP,那只能认栽了。

因此在网络传输过程中,最好不要分片。所以传输层也会对自己做出约束:

MSS(Maximum Segment Size,最大分段大小)

定义:TCP 传输层 能传输的单个 TCP 分段的最大数据部分字节数(仅包含 TCP 数据,不包含 IP 头和 TCP 头)。

MSS = MTU - IP头大小(通常20字节) - TCP头大小(通常20字节)

以太网下默认 MSS:1500 - 20 - 20 = 1460字节。

作用:TCP 握手时(SYN 包),双方会协商 MSS,确保 TCP 分段不会超过 MTU 导致分片,是 "避免 IP 分片" 的关键机制。

TCP发送的报文,一次一般不会超过MSS。这其实告诉我们TCP在滑动窗口时:

为什么没把窗口一股脑发出去,而是分成一个个小格子。

虽说我们拒绝分片,但是发生了分片也是没办法的事,还是要做出处理的。

首先16位标识就是唯一标记网络层的报文,确保报文分片之后还能通过16位标识找到自己的分片。

3位标志字段:第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到).

第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文.

第三位表示"更多分片",如果分片了的话,最后一个分片置为0,其他是1.类似于一个结束标记

13位分片偏移(framegamentoffset): 是分片相对于原始IP报文开始处的偏移.其实就是在表示当前分片在原报文中处在哪个位置.实际偏移的字节数是这个值 8得到的.因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了).

所以当IP报文大小超过MTU时,IP会根据报文分成8整除分片大小+报头大小的不同分片。

在远端收到分片后会根据13位分片偏移排序分片,检验每个分片的片偏移加上片大小是不是下一个分片的片偏移。如果是代表分片连贯。

再看看首部和尾部在不在,在的话就可以组装了。

其中首部自然就是片偏移为0,3位标志为001;尾部是片偏移非零,3位标志为000

相关推荐
BingoGo4 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack4 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
DianSan_ERP3 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
呉師傅3 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑
gihigo19983 天前
基于TCP协议实现视频采集与通信
网络协议·tcp/ip·音视频
QQ5110082853 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php