第十八篇:一文说清楚ICMP的底层原理
作为程序员或者网络工程师,有时候无法访问对方主机;导致这个现象的有很多原因,那要排查具体的网络原因,可能会用到ping的指令。而ping的底层实现是互联⽹控制报⽂协议(ICMP)。
ICMP 全称是 Internet Control Message Protocol,也就是互联⽹控制报⽂协议。
-
ICMP 功能都有啥?
ICMP 主要的功能包括:
① 确认 IP 包是否成功送达⽬标地址
② 报告发送过程中 IP 包被废弃的原因和改善⽹络设置等。
在 IP 通信中如果某个 IP 包因为某种原因未能达到⽬标地址,那么这个具体的原因将由 ICMP 负责通知。
注意:
① ICMP是基于IP协议工作的,但是它并不是传输层的功能,因此人们仍把它归结于网络层协议。
② ICMP只能搭配IPv4使用。如果是IPv6的情况下,需要使用ICMPv6。

如上图例⼦,主机 A 向主机 B 发送了数据包,由于某种原因,途中的路由器 2 未能发现主机 B 的存在,这时,路由器 2 就会向主机 A 发送⼀个 ICMP ⽬标不可达数据包,说明发往主机 B 的包未能成功。
ICMP 的这种通知消息会使⽤ IP 进⾏发送。
因此,从路由器 2 返回的 ICMP 包会按照往常的路由控制先经过路由器 1 再转发给主机 A 。收到该 ICMP包的主机 A 则分解 ICMP 的⾸部和数据域以后得知具体发⽣问题的原因。
-
ICMP报文格式

说明:
① 类型:1字节,说明该报文属于什么类型。
② 代码:1字节,说明ICMP报文的代码。
③ 检验和:2字节,检验ICMP报文是否有错误。
ICMP 包头的类型字段,⼤致可以分为两⼤类:

① 「查询报⽂类型」
ICMP协议报文里面的类型是0和8的时候,说明这是一个查询报⽂。

可以向对端主机发送回送请求的消息( ICMP Echo Request Message ,类型 8 ),也可以接收对端主机发回来的回送应答消息( ICMP Echo Reply Message ,类型 0 )。这里的回送就是有来有回的意思。
② 「差错报⽂类型」
ICMP协议报文里面的类型不是0和8的时候,说明这是一个差错报⽂。

目标不可达:
IP 路由器⽆法将 IP 数据包发送给⽬标地址时,会给发送端主机返回⼀个⽬标不可达的 ICMP 消息,并在这个消息 中显示不可达的具体原因,原因记录在 ICMP 包头的代码字段。
举例 6 种常⻅的⽬标不可达类型的代码:

a. ⽹络不可达
IP 地址是分为⽹络号和主机号的,所以当路由器中的路由器表匹配不到接收⽅ IP 的⽹络号,就通过 ICMP 协议以网络不可达( Network Unreachable )的原因告知主机。
b. 主机不可达
当路由表中没有该主机的信息,或者该主机没有连接到⽹络,那么会通过 ICMP 协议以主机不可达( Host Unreachable )的原因告知主机。
c. 协议不可达
当主机使⽤ TCP 协议访问对端主机时,能找到对端的主机了,可是对端主机的防⽕墙已经禁⽌ TCP 协议访问,那么会通过 ICMP 协议以协议不可达的原因告知主机。
d. 端⼝不可达
当主机访问对端主机 8080 端⼝时,这次能找到对端主机了,防⽕墙也没有限制,可是发现对端主机没有进程监听8080 端⼝,那么会通过 ICMP 协议以端⼝不可达的原因告知主机。
e. 需要进⾏分⽚但设置了不分⽚
发送端主机发送 IP 数据报时,将 IP ⾸部的分⽚禁⽌标志位设置为 1 。根据这个标志位,途中的路由器遇到超过MTU ⼤⼩的数据包时,不会进⾏分⽚,⽽是直接抛弃。
原点抑制消息(ICMP Source Quench Message):
在使⽤低速⼴域线路的情况下,连接 WAN 的路由器可能会遇到⽹络拥堵的问题。
ICMP 原点抑制消息的⽬的就是为了缓和这种拥堵情况。当路由器向低速线路发送数据时,其发送队列的缓存变为零⽽⽆法发送出去时,可以向 IP 包的源地址发送⼀个 ICMP 原点抑制消息。
收到这个消息的主机借此了解在整个线路的某⼀处发⽣了拥堵的情况,从⽽增⼤ IP 包的传输间隔,减少⽹络拥堵的情况。 然⽽,由于这种 ICMP 可能会引起不公平的⽹络通信,⼀般不被使⽤。
重定向消息(ICMP Redirect Message):
如果路由器发现发送端主机使⽤了「不是最优」的路径发送数据,那么它会返回⼀个 ICMP 重定向消息给这个主机。
在这个消息中包含了最合适的路由信息和源数据。这主要发⽣在路由器持有更好的路由信息的情况下。路由器会通过这样的 ICMP 消息告知发送端,让它下次发给另外⼀个路由器。
超时消息(ICMP Time Exceeded Message):
IP 包中有⼀个字段叫做 TTL ( Time To Live ,⽣存周期),它的值随着每经过⼀次路由器就会减 1,直到减到 0 时该 IP 包会被丢弃。
此时,路由器将会发送⼀个 ICMP 超时消息给发送端主机,并通知该包已被丢弃。
设置 IP 包⽣存周期的主要⽬的,是为了在路由控制遇到问题发⽣循环状况时,避免 IP 包⽆休⽌地在⽹络上被转发。
此外,有时可以⽤ TTL 控制包的到达范围,例如设置⼀个较⼩的 TTL 值。
- ping命令
ping的报文格式:

相⽐原⽣的 ICMP,这⾥多了两个字段:
① 标识符:⽤以区分是哪个应⽤程序发 ICMP 包,⽐如⽤进程 PID 作为标识符;
② 序号:序列号从 0 开始,每发送⼀次新的回送请求就会加 1 , 可以⽤来确认⽹络包是否有丢失。
使用方法:
ping + 域名或IP
ping命令执行细节:

① ping命令会发送一个ICMP Echo Request给对端;

每发出⼀个请求数据包,序号会⾃动加 1 。为了能够计算往返时间 RTT ,它会在报⽂的数据部分插⼊发送时间。
ICMP报文被ICMP协议的实现程序组织好后,交给网络层的程序处理,加上源地址IP与目的IP,再传给数据链路层,加上源MAC地址与目的MAC地址;然后发送出去

说明:源和目的IP为上图的IP
② 对端接收后,返回一个ICMP Echo Reply;
③ 注意是在主机A网络层发出ICMP Echo Request,在主机B接收到网络层,再发出ICMP Echo Reply;

在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明⽬标主机不可达;如果接收到了 ICMP 回送响应消息,则说明⽬标主机可达。
此时,源主机会检查,⽤当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
针对上⾯发送的事情,总结成了如下图:

当然这只是最简单的,同⼀个局域⽹⾥⾯的情况。如果跨⽹段的话,还会涉及⽹关的转发、路由器的转发等等。
但是对于 ICMP 的头来讲,是没什么影响的。会影响的是根据⽬标 IP 地址,选择路由的下⼀跳,还有每经过⼀个路由器到达⼀个新的局域⽹,需要换 MAC 头⾥⾯的 MAC 地址。
说了这么多,可以看出 ping 这个程序是使⽤了 ICMP ⾥⾯的 ECHO REQUEST(类型为 8 ) 和 ECHO REPLY(类型为 0)。
- traceroute命令
traceroute充分利⽤ ICMP 差错报⽂类型;(在UNIX、MacOS中是这个命令,⽽在Windows中对等的命令叫做 tracert )。
- 使用
Windows:tracert + 域名或IP地址
Linux/macOS:traceroute + 域名或IP地址
① 定位从源主机到目标主机之间经过了哪些路由器,以及到达各个路由器的耗时
原理: traceroute使用UDP,主机之间通信,网络层IP数据报的首部中,有个TTL字段(Time To Live)。TTL的作用是,设置IP数据报被丢弃前,最多能够经过的节点数。
每经过一个中间节点,再向下一个节点转发数据前,都会将TTL减1。如果TTL不为0,则将数据报转发到下一个节点;否则,丢弃数据报,并返回错误,错误类型是时间超时。

问题:如何判断报文是否到达目标主机?
traceroute发送UDP报文时,将目标端口设置为较大的值( 33434 - 33464),避免目标主机B上该端口有在实际使用。
当报文到达目标主机B,目标主机B发现目标端口不存在,则向源主机A发送ICMP报文(Type=3,Code=3),表示目标端口不可达。
源主机A收到差错报文,发现Type=3,Code=3,知道已经到达目标主机B。记录下IP、耗费,检测结束。
② 故意设置不分⽚,从⽽确定路径的 MTU
有的时候我们并不知道路由器的 MTU ⼤⼩,以太⽹的数据链路上的 MTU 通常是 1500 字节,但是⾮以外⽹的 MTU 值就不⼀样了,所以我们要知道 MTU 的⼤⼩,从⽽控制发送的包⼤⼩。

它的⼯作原理如下:
⾸先在发送端主机发送 IP 数据报时,将 IP 包⾸部的分⽚禁⽌标志位设置为 1。根据这个标志位,途中的路由器不会对⼤数据包进⾏分⽚,⽽是将包丢弃。
随后,通过⼀个 ICMP 的不可达消息将数据链路上 MTU 的值⼀起给发送主机,不可达消息的类型为「需要进⾏分⽚但设置了不分⽚位」。发送主机端每次收到 ICMP 差错报⽂时就减少包的⼤⼩,以此来定位⼀个合适的 MTU 值,以便能到达⽬标主机。
相关文章:
第十八篇:一文说清楚ICMP的底层原理
作为程序员或者网络工程师,有时候无法访问对方主机;导致这个现象的有很多原因,那要排查具体的网络原因,可能会用到ping的指令。而ping的底层实现是互联⽹控制报⽂协议(ICMP)。 ICMP 全称是 Internet Contr…...
【优选算法】(第三十二篇)
目录 ⼆进制求和(easy) 题目解析 讲解算法原理 编写代码 字符串相乘(medium) 题目解析 讲解算法原理 编写代码 ⼆进制求和(easy) 题目解析 1.题目链接:. - 力扣(LeetCode&a…...
线程(四)线程的同步——条件变量
文章目录 线程线程的同步和互斥线程同步--条件变量什么是线程同步示例--条件变量的使用示例--使用两个线程对同一个文件进行读写示例--一个读者一个写者使用条件变量来实现同步 线程 线程的同步和互斥 线程同步–条件变量 是一个宏观概念,在微观上包含线程的相互…...
二维数组的旋转与翻转(C++)(上(这只是简单讲解))
二维数组的旋转与翻转(C) 引言 在计算机科学中,二维数组是一种常见的数据结构,广泛应用于图像处理、数据挖掘、机器学习等多个领域。二维数组的旋转与翻转是处理二维数据时经常需要用到的操作。本文将详细介绍二维数组的旋转与翻…...
【在Linux世界中追寻伟大的One Piece】System V共享内存
目录 1 -> System V共享内存 1.1 -> 共享内存数据结构 1.2 -> 共享内存函数 1.2.1 -> shmget函数 1.2.2 -> shmot函数 1.2.3 -> shmdt函数 1.2.4 -> shmctl函数 1.3 -> 实例代码 2 -> System V消息队列 3 -> System V信号量 1 -> Sy…...
【大数据】Spark弹性分布式数据集RDD详细说明
文章目录 整体介绍一、定义与特性二、操作与转换三、存储级别与持久化四、依赖关系与容错机制五、优化与性能调优 常见操作支持的数据格式1.文本文件 (Text Files)2. CSV 文件3. JSON 文件4. Parquet 文件5. Sequence Files6.Hadoop文件读取A. 读取HDFS上的文本文件B. 使用Hado…...
人参玉桂膏简介
一、产品基本信息 产品名称:人参玉桂膏 产品类别:植物饮料(专为特定体质设计) 配料:精选薏苡仁、荷叶、玉米须、赤小豆等纯然植物成分,辅以麦芽糖醇液、低聚果糖调节口感,陈皮、肉桂、人参&…...
消费者Rebalance机制
优质博文:IT-BLOG-CN 一、消费者Rebalance机制 在Apache Kafka中,消费者组 Consumer Group会在以下几种情况下发生重新平衡Rebalance: 【1】消费者加入或离开消费者组: 当一个新的消费者加入消费者组或一个现有的消费者离开消费…...
消息队列介绍
一、ActiveMQ 优点:性能单台(6000)成熟,已经在很多公司得到应用。各种协议支持好,有多个语言的成熟客户端 缺点:性能较弱,缺乏大规模吞吐的场景的应用,有江河日下之感 二、RabbitMQ…...
告别@Value,Spring Boot 3.3更优雅的配置注入方案
在Spring Boot的早期版本中,我们常使用Value注解来注入配置文件中的属性值。然而,这种方式虽然简单直接,却存在一些局限,比如它只能注入基本类型的值,并且需要显式地在每个需要注入的字段上使用注解。随着Spring Boot的…...
甲虫身体图像分割系统源码&数据集分享
甲虫身体图像分割系统源码&数据集分享 [yolov8-seg-EfficientRepBiPAN&yolov8-seg-C2f-FocusedLinearAttention等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challen…...
Qt - QMenu
QMenu 1、menu转string输出 //GlobalEnum.h #include <QObject> #include <QMetaEnum> class GlobalEnum : public QObject {Q_OBJECT public:EnumTest();enum Enum_Test{ZhangSan 0,WangWu,};Q_ENUM(Enum_Test) };#define EnumToString(e) \ QMetaEnum::fromTy…...
舵机驱动详解(模拟/数字 STM32)
目录 一、介绍 二、模块原理 1.舵机驱动原理 2.引脚描述 三、程序设计 main.c文件 servo.h文件 servo.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 舵机(Servo)是在程序的控制下,在一定范围内连续改变输出轴角度并保持的电机系统。即舵机只支持…...
dvwa:文件包含、文件上传
文件包含 本地文件包含(敏感信息泄露)和远程文件包含(命令执行) 本地文件包含一般包含一些本地的敏感文件,如:/etc/passwd或/etc/shadow等 远程文件包含能使得服务器代码执行,如包含黑客vps的…...
基于 C# .NET Framework 4.0 开发实现 WCF 服务实例详解(二)——实现Windows服务内嵌WCF服务
目录 引言 1. 创建一个新的Windows服务项目 2. 添加WCF服务 2.1 添加服务接口和实现 2.2 添加服务配置 3. 实现Windows服务 3.1 修改Service1类 3.2 在项目中添加ServiceInstaller 4. 安装和运行Windows服务 4.1 编译项目 4.2 使用InstallUtil.exe安装服务 …...
【ArcGIS/C#】调用控制台处理代码
代码示例 private static string[] run_conda_process(string command, Action<string> on_msg, CancellationTokenSource cancel){if (string.IsNullOrEmpty(command)){return new string[]{null,ArcGIS.Desktop.Internal.Core.Conda.Resources.Error_Unexpected + &qu…...
06_23 种设计模式之《适配器模式》
文章目录 一、适配器模式基础知识实例 一、适配器模式基础知识 适配器模式定义:将一个类的接口转换成客户希望的另一个接 口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可 以一起工作。 Client:客户端,调用自已需要的领域接口…...
Go语言--快速入门
Go语言特点 我们先看一下简单的Go语言程序 package mainimport "fmt"func main() { // 错误,{ 不能在单独的行上fmt.Println("Hello, World!") }我们可以看到外型非常像我们的JAVA,但是不需要;作为结尾,…...
京东云主机怎么用?使用京东云服务器建网站(图文教程)
京东云主机怎么用?非常简单,本文京东云服务器网jdyfwq.com使用以使用京东云服务器搭建WordPress博客网站为例,来详细说下京东云主机的使用方法。使用京东云服务器快速搭建WordPress网站教程,3分钟基于应用镜像一键搞定,…...
Linux 基础入门操作-实验七 进程的介绍
实验七 进程的介绍 7.1 进程基础概念 Linux进程在内存中包含三部分数据:码段、堆栈段和数据段。代码段存放了程序的代码。代码段可以为机器中运行同一程序的数个进程共享。堆栈段存放的是子程序的返回地址、子程序的参数及程序的局部变量。而数据段则存放程序的全…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
