计算机网络:网络层 - IPv4数据报 ICMP协议
计算机网络:网络层 - IPv4数据报 & ICMP协议
- IPv4数据报
- [版本 : 首部长度 : 区分服务 : 总长度]
- [标识 : 标志 : 片偏移]
- [生存时间 : 协议 : 首部检验和]
- [可变部分 : 填充字段]
- ICMP协议
IPv4数据报
一个IPv4数据报
,由首部和数据两部分组成:
而首部又分为两部分:
上图中,首部又分为固定部分
和可变部分
,固定部分
的长度为20 byte
,而可变部分的长度在0 byte
到40 byte
之间。每一行占32 bit
也就是4 byte
。接下来就讲解这个首部各个字段的含义。
[版本 : 首部长度 : 区分服务 : 总长度]
- 版本
占4 bit
,表示该IP数据报
使用的版本,目前广泛使用的IP协议
版本号为4
。
- 首部长度
由于可变部分
的存在,IPv4数据报
的首部长度是不确定的,所以需要额外的字段来标识整个首部的长度。首部长度
占4 bit
,4 bit
可以表示的最大数字为二进制1111
,也就是15
。但是IPv4数据报
的最大长度为60 byte
,这是4 bit
好像不够用啊。
其实首部长度
字段的值,是以4 byte
为单位的,也就是说如果首部长度的值为15
,表示有15 * 4 = 60 byte
,这样4 bit
刚好可以表示最大的首部长度。另外的,由于首部长度单位的限制,所以IPv4
数据报首部的长度必须为四字节的整数倍。
- 区分服务
占8 bit
,用于提供不同等级的服务,也就是说IPv4数据报
的服务分了多个等级,可以通过该字段来选择不同等级。大部分情况下不使用这个字段。
- 总长度
占16 bit
,指明首部和数据部分的总长度,单位为byte
。由于只占16 bit
,所以整个IPv4数据报
总长度不超过665535 byte
。当然一般来数据报的长度是数据链路层的MTU
限制的。
[标识 : 标志 : 片偏移]
那么一个数据报的内容超过了MTU
该怎么办?此时就要进行分片
操作,将一个数据报分为多个小份的数据报。
假设现在有一个长度为3820 byte
的数据报,首部长度为20 byte
,现在MTU
限制为1420 byte
,那么我们就要把这个3820 byte
的打数据报分片为多个小的数据报。
如下图:
我们把这个数据报分片为了三个小数据报,第一个数据报的长度为20 + 1400
,第二个数据报的长度为20 + 1400
,第三个数据报的长度为20 + 1000
,其中20
表示每个分片后数据报的首部。而分片的规则为:优先填满前面的数据报,而不是将数据平均分配到每个数据报中。
将一个数据报分片后,会产生以下问题:
- 接收方如何知道这些分片后数据报来源于同一个数据报
- 接收方如何知道自己是否收到了所有分片
- 接收方如何知道这些分片的顺序
IPv4数据报
首部中的第二行字段,就是用来解决分片的问题的:
- 标识
占16 bit
,这是一个计数器,用于区分不同的数据报,或者辨别相同的数据报。
比如说发送方前一个发送的数据报的标识 = 12345
的数据报,那么发送方发送的下一个数据报的标识就应该是12345 + 1 = 12346
。这样接收方就可以辨别出这是两个不同的数据报。
但是如果把一个数据报分片为多个数据报,那么分片出来的所有数据报,共用一个标识
字段。此时接收方收到多个分片后,就可以判断出来这些分片原本属于同一个数据报。
- 片偏移
占13 bit
,其用于指出一个数据报在分片后再原数据报中的相对位置。片偏移以8 byte
为单位。
比如刚才的案例中:
对于分片1
,其第一个字节为0
,片偏移 = 0 / 8 = 0
;
对于分片2
,其第一个字节为1400
,片偏移 = 1400 / 8 = 175
;
对于分片3
,其第一个字节为1800
,片偏移 = 2800 / 8 = 350
;
由于片偏移
只能是整数,所以数据报总长度必须是8 byte
的整数倍!
- 标志
占3 bit
,三个比特位单独解析,从低位到高位分别是MF
位,DF
位,和保留位
。其中保留位
是保留给以后使用的,目前没有意义,保留位必须为0
。
MF(More Fragment)
位,用于表示该数据报后面还有没有分片。一个数据报被分片后,除去最后一个分片外,所有的分片的MF = 1
,表示这个分片后还有分片;而最后一个分片的MF = 0
,表示该分片已经是最后一个分片了。
MF
位结合片偏移
,可以用于确认是否接收到了所有的分片。当接收方接收到了MF = 0
的分片,就说明已经收到了末尾的分片,随后获取该分片的片偏移
从而得知前面总共有多少数据,再检测自己之前收到的数据,就可以知道自己是否受到了所有分片了。
DF(Don't Fragment )
位,该位表示一个数据报是否允许分片,如果DF = 0
表示允许分片,如果DF = 1
表示不允许分片。
=如果一个数据报的长度超过了MTU
,并且DF = 1
不允许分片,此时会直接丢弃这个数据报,并向上层发送错误信息,表示该数据报不能传递。
再回到这个案例:
接下来我画一个表格,表示这三个分片的各字段值,假设分片前标识 = 12345
:
数据报 | 标识 | MF | DF | 保留位 | 片偏移 |
---|---|---|---|---|---|
分片前 | 12345 | 0 | 0 | 0 | 0 |
分片1 | 12345 | 1 | 0 | 0 | 0 |
分片2 | 12345 | 1 | 0 | 0 | 175 |
分片3 | 12345 | 0 | 0 | 0 | 350 |
[生存时间 : 协议 : 首部检验和]
- 生存时间
占8 bit
,又叫做TTL(Time TO Live)
,该字段由源主机设置,路由器每次转发时TTL
要减一。当TTL = 0
时,路由器不再转发该报文,而是将其丢弃,即生存时间到期了。
- 协议
占b bit
,用于表示数据部分的内容使用了何种协议,常见协议字段取值如下:
- 首部检验和
占16 bit
,用于检验数据报的首部是否发生错误,注意只检验首部,不会检验数据部分。
以下是计算 IP 数据报首部校验和的步骤:
- 将首部所有字段视为 16 位字,并进行二进制求和(简单来说就是把首部看为16比特一组)
- 对求和结果进行进位运算
- 对求和结果进行按位取反
举例:
假设一个 IP 数据报的首部如下:
字段 | 值 | 二进制 |
---|---|---|
版本 | 4 | 0100 |
首部长度 | 5 | 0101 |
服务类型 | 0 | 0000 |
总长度 | 100 | 0000 0000 0110 0100 |
标识 | 1234 | 0000 0100 1011 0110 |
标志 | 0 | 000 |
片偏移 | 0 | 0 0000 0000 0000 |
生存时间 | 8 | 0000 1000 |
协议 | 6 | 0000 0110 |
首部校验和 | 0 | 0000 0000 0000 0000 |
源地址 | 192.168.1.1 | 1100 0000 1010 1000 0000 0001 0000 0001 |
目的地址 | 10.0.0.1 | 0000 1010 0000 0000 0000 0000 0000 0001 |
注意:上表中的首部检验和
值是固定的,因为目前还在计算首部检验和
,该字段在计算前视为0
。
- 将首部所有字段视为 16 位字,并进行二进制求和:
0100 0101 0000 0000 [版本+首部长度+服务类型]
0000 0000 0110 0100 [总长度]
0000 0100 1011 0110 [标识]
0000 0000 0000 0000 [标志+片偏移]
0000 1000 0000 0110 [生存时间+协议]
0000 0000 0000 0000 [首部检验和]
1100 0000 1010 1000 [源地址前16位]
0000 0001 0000 0001 [源地址后16位]
0000 1010 0000 0000 [目的地址前16位]
0000 0000 0000 0001 [目的地址后16位]
对以上所有数进行加法运算得到:
0001 0001 1101 1100 1010
可以看到,我们原先的所有数都是16
位,这里变成了17
位,即发生了进位,此时就要进行第二步进位运算。
- 对求和结果进行进位运算:
0001 0001 1101 1100 1010
拆出后16
位:0001 1101 1100 1010
,多出的位是0001
,也就是1
。对于进位,我们的处理方式为:将其重新加到后16
位中。
也就是:
0001 1101 1100 1010
+
0000 0000 0000 0001
结果为:
0001 1101 1100 1011
注意:该部分在第二次计算后,有可能还会发生进位,此时要重复该过程,直到没有进位。
- 对求和结果进行按位取反:
最后把结果取反:
1110 0010 0011 0100
这个值就是首部检验和
。
接收方接收到数据报后,只需要以相同的方式进行计算,如果结算结果为0
,说明首部没有发生错误。如果为非0
,说明发生了错误,丢弃该报文。
流程图如下:
剩下的目的地址
,源地址
很好理解,不做讲解。
[可变部分 : 填充字段]
可选字段
用来填入一些选项,可以用来支排错,测量等各种安全措施,但是实际上很少被使用。我们不过多讲解该字段。
对于填充
,这是因为可选字段
的长度不确定,而数据报的首部长度必须是4 byte
的整数倍,这个填充
字段,就是为了把可选字段
填充到4 byte
的整数倍的。
ICMP协议
ICMP(Internet Control Message Protocol,互联网控制报文协议)
是 TCP/IP 协议族中的一个重要组成部分,它负责在网络设备之间传递控制信息,例如错误报告、状态信息等。
ICMP报文
被封装在IP数据报
的数据部分,但是其是属于IP层
的协议,而不是高层协议
ICMP
报文格式:
字段 | 长度 | 描述 |
---|---|---|
类型 | 8 位 | 标识 ICMP 报文的类型,例如错误报告、查询等。 |
代码 | 8 位 | 对类型字段的进一步解释,例如错误的具体原因。 |
校验和 | 16 位 | 用于校验 ICMP 报文本身的完整性。 |
而第二行这个区域,会根据不同类型的报文,而有不同的格式。
ICMP
报文主要分为两类:ICMP 差错报告
和ICMP 询问报文
而这两个类型又被细分为更多的类型,在此我举例一部分:
- 终点不可达:当主机或路由器不能交付数据报时,就向源点发送
终点不可达
报文,再根据代码
字段来描述更加具体的原因。
以上示例中,路由器R1
受到数据报后,不知道如何转发,于是丢弃数据报,发送终点不可达
。
- 源点抑制:当主机或路由器因为阻塞而丢弃数据报时,就向源点发送
源点抑制
报文
以上示例中,主机H2
发送拥塞,丢弃报文后向源点发送源点抑制
报文
- 时间超过:当
IP数据报
中的RTT
减为0
时,丢弃该数据报,向源点发送时间超过
报文
以上示例中,数据报在经过R2
时RTT = 0
,,丢弃该数据报,向源点发送时间超过
报文
- 参数问题:当主机或路由接收到
IP数据报
后,会检测其中的校验和
字段,如果发现错误,就丢弃该报文,并向源点发送参数问题
报文
以上示例中,当路由器R1
收到IP数据报
后,检测其中的校验和
字段,如果发现首部出现错误,就丢弃该报文,并向源点发送参数问题
报文
- 改变路由:当主机或路由收到数据报后,发现可以通过更好的路线传送,就丢弃该报文,并向源点发送
改变路由
报文
以上示例中,当路由器R1
收到IP数据报
后,发现可以通过R4
更快传送,就丢弃该报文,并向源点发送改变路由
报文。
以上只是一部分示例,以上全部示例中,各个类型的ICMP 差错报告报文
对应的类型
字段的值如下:
类型 | 终点不可达 | 源点抑制 | 时间超过 | 参数问题 | 改变路由 |
---|---|---|---|---|---|
字段值 | 3 | 4 | 11 | 12 | 5 |
对于ICMP 询问报文
,也有部分类型字段取值:
类型 | 回送请求/回答 | 时间戳请求/回答 |
---|---|---|
字段值 | 8 / 0 | 13 / 14 |
对于询问报文,就不再举例了。
讲完了ICMP
的首部,再来看看ICMP
的数据部分
,其实ICMP差错报告报文
的数据部分格式也是固定的。
格式如下:
取出IP数据报
的首部,以及数据部分的前八个字节,构成ICMP
的数据部分。
主要是要在ICMP
报文中体现一些重要信息,以便源点分析具体原因。而大部分重要信息都在首部中,所以存储了IP数据报
的首部。另外的IP数据报
的数据部分的前八个字节,还包含一些运输层端口相关信息,也被纳入ICMP
的数据部分。
相关文章:

计算机网络:网络层 - IPv4数据报 ICMP协议
计算机网络:网络层 - IPv4数据报 & ICMP协议 IPv4数据报[版本 : 首部长度 : 区分服务 : 总长度][标识 : 标志 : 片偏移][生存时间 : 协议 : 首部检验和][可变部分 : 填充字段] ICMP协议 IPv4数据报 一个IPv4数据报,由首部和数据两部分组成ÿ…...

【需求设计】软件概要设计说明怎么写?概要设计说明书实际项目案例(63页Word直接套用)
软件概要设计说明书书写要点可以归纳为以下几个方面,以确保文档的准确性、完整性和可读性: 引言 目的:介绍编写该文档的目的、主要内容及目标读者。 背景:说明被开发软件的名称、项目提出者、开发者等背景信息。 需求概述…...

网络编程2----UDP简单客户端服务器的实现
首先我们要知道传输层提供的协议主要有两种,TCP协议和UDP协议,先来介绍一下它们的区别: 1、TCP是面向连接的,UDP是无连接的。 连接的本质是双方分别保存了对方的关键信息,而面向连接并不意味着数据一定能正常传输到对…...

服务架构的设计原则
墨菲定律与康威定律 在系统设计的时候,可以依据于墨菲定律 任何事情都没有表面上看起来那么简单所有的事情都会比你预计的时间长可能出错的事总会出错担心的某一个事情的发送,那么它就更有可能发生 在系统划分的时候,可以依据康威定律 系…...

Day 14:2938. 区分黑球和白球
Leetcode 2938. 区分黑球和白球 桌子上有 n 个球,每个球的颜色不是黑色,就是白色。 给你一个长度为 n 、下标从 0 开始的二进制字符串 s,其中 1 和 0 分别代表黑色和白色的球。 在每一步中,你可以选择两个相邻的球并交换它们。 返…...

部署YUM仓库及NFS共享服务
YUM概述 YUM 基于RPM包构建的软件更新机制 可以自动解决依赖关系 所有软件包由集中的YUM软件仓库提供 YUM只允许一个程序运行,虽然不影响命令的使用。DNF后,允许多个程序允许 YUM的配置文件在/etc/yum.conf 网络源(所有以repo为结尾都是源&am…...

web学习笔记(六十五)
目录 1. Hash模式和History模式 2. 导航守卫 3. 路由元信息 4.路由懒加载 1. Hash模式和History模式 Hash模式(哈希模式)和History模式(历史模式)是匹配路由的两种模式,一般默认配置Hash模式,可以在in…...

66. UE5 RPG 实现远程攻击武器配合角色攻击动画
在制作游戏中,我们制作远程攻击角色,他们一般会使用弓箭,弩,弹弓等武器来进行攻击。比如你使用弓箭时,如果角色在播放拉弓弦的动画,但是弓箭武器没有对应的表现,会显得很突兀。所以,…...
用 Python 编写自动发送每日电子邮件报告的脚本,并指导我如何进行设置
编写一个自动发送每日电子邮件报告的脚本涉及几个步骤。我们需要使用 Python 编写脚本,并使用一些库来发送电子邮件。下面是一个示例脚本和设置步骤。 第一步:安装必要的库 我们需要安装 smtplib 和 email 库。可以通过以下命令安装: pip …...

AI大模型的战场:通用与垂直的较量
目录 AI大模型的战场:通用与垂直的较量 1.引言 2.通用大模型的优势 2.1 概念 2.2 谷歌的BERT模型 2.3 OpenAI的GPT模型 2.4 微软的Visual Studio Code 2.5 结论 3.垂直大模型的崛起 3.1 概念 3.2 医疗影像分析的AI模型 3.3 自动驾驶领域的AI模型 3.4 金…...

单目标应用:基于人工原生动物优化器APO的微电网优化(MATLAB代码)
一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献: [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、人工原生动物优化算法求解微电网 2.1算法简介 人工原生动物优化器&am…...

USB端口管控软件|USB端口控制软件有哪些(小技巧)
USB端口管控软件成为了保障企业数据安全的重要手段。 本文将为您介绍几款知名的USB端口控制软件,并分享一些实用的小技巧,帮助您更好地管理US端口,确保企业信息安全。#usb接口# 一、USB端口控制软件推荐 1,域智盾 域智盾是一…...

CorelDRAW2024官方最新中文破解版Crack安装包网盘下载安装方法
在设计的世界里,软件工具的更新与升级总是令人瞩目的焦点。近期,CorelDRAW 2024中文版及其终身永久版的发布,以及中文破解版Crack的出现,再次掀起了设计圈的热潮。对于追求专业精确的设计师而言,了解这些版本的下载安装…...

Mysql学习(八)——多表查询
文章目录 五、多表查询5.1 多表关系5.2 多表查询概述5.3 内连接5.4 外连接5.5 自连接5.6 联合查询5.7子查询5.8 总结 五、多表查询 5.1 多表关系 概述:项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,…...

LabVIEW进行图像拼接的实现方法与优化
在工业检测和科研应用中,对于大尺寸物体的拍摄需要通过多次拍摄后进行图像拼接。LabVIEW 作为强大的图形化编程工具,能够实现图像拼接处理。本文将详细介绍LabVIEW进行图像拼接的实现方法、注意事项和提高效率的策略。 图像拼接的实现方法 1. 图像采集…...

纷享销客安全体系:安全合规认证
安全合规认证是指组织通过独立的第三方机构对其信息系统和数据进行评估和审查,以确认其符合相关的安全标准、法律法规和行业要求的过程。 安全合规认证可以帮助组织提高信息系统和数据的安全性,并向客户、合作伙伴和监管机构证明其符合相关的安全标准和…...

推荐这两款AI工具,真的很好用
巨日禄 巨日禄是一款由杭州巨日禄科技有限公司开发的AI工具,主要功能是将文本内容转换为视频。该工具通过分析大量的剧本数据和影视作品,为用户提供各种类型的故事情节和角色设置,帮助用户快速找到灵感,减少构思剧本的困难和犹豫。…...
装饰器在实际开发中的作用
首先先说说装饰器的整体优点。 使用装饰器可以实现代码的模块化、可重用性。当需要对多个函数进行相同的功能增强时,通过装饰器可以避免重复代码的编写,提高开发效率。 1、权限检查:通过装饰器可以在函数执行之前检查用户权限,决…...

JVM学习-监控工具(三)
jconsole 从Java5开始,在JDK中自带的java监控和管理控制台用于对JVM中内存、线程、和类等的监控,是一个基本JMX(java management extendsions)的GUI性能监控工具 三种连接方式 Local:使用JConsole连接是一个正在本地系统运行的JVM…...
GPU显卡计算能力怎么算?
GPU的算力指的是什么? GPU的计算能力可以使用FLOPS表示,FLOPS是floating-point operations per second的缩写,表示“每秒所执行的浮点运算次数”。是被用来估算处理的计算能力 1 MFLOPS 每秒可以执行一百万(10^6)次浮点运算 1 GFLOPS 每秒可以执行十…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...