IP 是"尽力而为"的(3.2)——包丢了它不出声。可网络总得有人报信:送不到要说一声、路上超时要说一声。干这活的就是 ICMP(网际控制报文协议)——它不传你的业务数据,专门传"关于数据的信息",是网络自己的系统消息。你天天用的 ping 和 tracert,都是它在干活。
前面几节陆续露过几面,当时都没展开:3.4 Demo18 那句「需要分片但 DF 置位」、3.7 的「TTL 传输中过期」、2.4 起就在用的 ping——它们全是 ICMP。本节把这条线一次收干净。
一、为什么需要 ICMP
问题:IP 只管送,不管汇报
IP 的工作方式是"尽力而为"(best effort): - 它不确认(不问你收到没有) - 它不重传(丢了就算了) - 它不出声(送不到也不告诉你)
这对路由器很省事,但对发送方是个麻烦:不知道出了什么事,就没法做反应——是对方不在?是路走不通?还是我的包太大?分不清就只能瞎猜。
答案:专门派一个"报信的"
ICMP(Internet Control Message Protocol,网际控制报文协议)就是干这个的。它的定位要记准:
ICMP 不传业务数据。它传的是"关于数据的信息"。
打个比方:快递员不负责给你送包裹,但包裹派不出去时,他会给你发一条系统短信——"收件地址不存在,已退回"。这条短信不是你的包裹,但它在告诉你包裹的下场。ICMP 就是那条短信。
它住在哪一层
ICMP 报文也装在 IP 包里——看 IP 首部的"协议"字段就能认出来(3.7 那张表里的 1):
| 协议号 | 里面装的是 |
|---|---|
| 6 | TCP |
| 17 | UDP |
| 1 | ICMP |
所以 ICMP 归网际层(跟 IP 是同一个办公室的同事),不是传输层——虽然它看起来"像"在传消息。
二、两大类报文
(对应上面第一张图)ICMP 报文按用途分两大类:
第一种:差错报告——"出事了,回禀发件人"
| 类型 | 名字 | 什么时候发 |
|---|---|---|
| 类型 3 | 终点不可达 | 找不到收件人(还会用"代码"进一步细分,见下) |
| 类型 11 | 超时 | 包在网里转太久(TTL 减到 0,收 3.7) |
| 类型 12 | 参数问题 | 包头里有字段写错了 |
| 类型 5 | 重定向 | "有更近的路,下次改走那边" |
类型 3 的"代码"细分很实用——同样是"不可达",原因完全不同:
| 代码 | 含义 | 你怎么会遇到 |
|---|---|---|
| 0 | 网络不可达 | 整条路没通 |
| 1 | 主机不可达 | 路通了,但目标机器不在 |
| 3 | 端口不可达 | 机器在,但那个端口上没程序在听(UDP 的唯一反馈,见第六部分) |
| 4 | 需要分片但 DF 置位 | 3.4 Demo18 里那句话的正式出处 |
ICMP 报文最前面是两个字节:类型(1 字节,决定"是什么大事")+ 代码(1 字节,决定"细分成哪种小情况")。上面「类型 3 / 代码 4」的写法就是这么来的——先认大事,再看细分,这个读法在抓包和排障时很常用。
第二种:询问——"主动问一句,看看对方怎么样"
| 类型 | 名字 | 干什么 |
|---|---|---|
| 类型 8 / 0 | 回送请求 / 回送应答 | 这就是 ping |
| 类型 13 / 14 | 时间戳请求 / 应答 | 问对方"现在几点",用来测时间 |
两类报文的根本区别: - 差错报告:出了事才发,只有去程(不需要对方回答) - 询问:主动发出,成对往返(有问必有答)
另外有个容易漏的对比:IP 首部校验和只管头部(3.7),而 ICMP 的校验和覆盖整个 ICMP 报文——两种校验和的范围不一样,别混。
三、差错报文的一条关键规矩
(对应上面第二张图)这是 ICMP 设计里最聪明的一手:
差错报文总是回给"原包的源地址",而且报文里装着原包的"身份证复印件":原 IP 包的首部 + 前 8 字节数据。
为什么要带复印件?
因为发送方可能同时开了几十条连接。如果只告诉它"出错了",它根本不知道该重传哪个、该放弃哪个。而 TCP/UDP 头最前面的 8 个字节里,正好就是源端口和目的端口——有了这 8 字节,发送方一看就知道:
"原来是我访问那个网站的那条连接,端口 50000 那条。"
这一手让 ICMP 从"模糊的通知"变成了"精确的定位"。没有这 8 字节,差错报告基本没用。
顺带一个反直觉的点:差错报文不转发给目标。因为目标根本没收到那个包(或收到了也帮不上忙),真正需要知道的是发的人。
四、ICMP 只报告,不修复
这一点必须拎清:
| ICMP 做了 | ICMP 不做 |
|---|---|
| 告诉发送方"出了什么事" | 不重传、不换路、不改变什么 |
真正"处理"的是两头: - 重传是 TCP 的活(3.5 的超时重传) - 调小包是发送方自己的活(收到"需要分片但 DF 置位"后,主动把包改小) - 报错给用户是应用程序的活
又是"分层各管一段":ICMP 当信使,TCP 当管家。
它只负责传一句"出什么事了",不做任何决策。所以它实现简单、开销极小——一台路由器每转发几个包才可能发一条 ICMP,绝大多数包根本不触发。
五、四条"不发"的规矩
ICMP 差错报文不是想发就发,标准规定了四种情况不发:
| 情况 | 为什么 |
|---|---|
| 对 ICMP 差错报文本身,不再发差错报告 | 否则你报我、我报你,无限循环 |
| 对分片后的非第一片不发 | 第一片才带完整的端口信息,后面的片说不清 |
| 对广播 / 组播地址不发 | 一个包发给全段,回了就会炸一片 |
对 127.0.0.1、0.0.0.0 这类特殊地址不发 |
没意义 |
这几条都是为了别把网络搞得更乱——报信是为了帮忙,不是为了添乱。
六、ICMP 的实战:ping 与 UDP 的命运
ping = ICMP 回送请求 / 应答
ping 做的就一件事:发一个类型 8,对方回一个类型 0。
因此它同时验证了三件事:对方在不在、路通不通、来回要多久。而且应答里会把请求带的数据原样带回,所以还能顺便确认数据没被改坏。
tracert = ICMP 超时
tracert 靠的是不断制造"TTL 用完"的现场,让沿途每台路由器回一条类型 11(3.7 Demo21 详细讲过)。它本质是在收集 ICMP 差错报告。
UDP 唯一的"反馈"来自 ICMP
这一条很关键。UDP 是没有确认机制的(3.3)——包发出去,有没有人接它完全不知道。
但如果目标主机发现"这个 UDP 包的端口上没程序在听",它会回一条 ICMP 类型 3 / 代码 3(端口不可达)。
UDP 自己不会告诉你"没人收",ICMP 才会。这也是为什么一些基于 UDP 的服务(DNS、游戏、音视频)出问题时,抓包里能看到"端口不可达"——这是它唯一能拿到的线索。
但要注意:很多防火墙会连 ICMP 一起拦,那就连这条线索都没了,表现成"一直没回音"。
七、ICMPv6:不只是"加个 v6"
IPv6 里 ICMP 升成了 ICMPv6,而且职责重得多——它不只报错,还承担了这些正经活:
| 用途 | 原来谁干 | 现在谁干 |
|---|---|---|
| 找 MAC 地址 | ARP(3.16) | ICMPv6 的邻居发现 NDP(抓包看到的是 NS / NA) |
| 找路由器 / 自动配地址 | DHCP、路由器通告 | ICMPv6 |
| 报错、ping | ICMP | ICMPv6(ping6) |
在 IPv4 世界里,"禁 ping"(拦 ICMP)是常见的安全策略,问题不大。 但 IPv6 下绝不能一刀切拦掉 ICMPv6——地址解析、地址自动配置全靠它,拦掉的后果是连邻居都认不出来,网络直接瘫痪。
正确做法是按类型放行:邻居发现、差错报告必须放,回送请求可酌情。
八、动手 Demo29:亲眼看看 ICMP 在说什么
-
看最基本的成对往返
ping www.baidu.com每一行回复 = 一次"类型 8 出去、类型 0 回来"。顺便看看"时间"(往返毫秒)和TTL=(收 3.7 的跳数估算)。 -
对照两种"不通"的说法(本节最实用的一条)
ping -n 1 -w 1000 8.8.8.8ping -n 1 -w 1000 1.2.3.4回来多半是两种完全不同的措辞: - 「请求超时」——没人回音,很可能被中途丢掉了或对方不理你
- 「无法访问目标主机」——收到了 ICMP 差错报文,是网络明确告诉你"送不到"
这两种不是一回事:一个是"没消息",一个是"有坏消息"。排障时方向完全不同。
-
亲手触发一条 ICMP 超时差错报文
ping -i 1 www.baidu.com报「TTL 传输中过期」——这就是类型 11 的原文(收 3.7 Demo21)。 -
看
tracert里的* * *tracert -4 www.baidu.com某几跳显示* * *= 那台设备不回 ICMP(很多运营商设备为了省事或安全,直接忽略)。不代表它坏了、也不代表路断了——后面的跳照样能通。 -
30 秒实验:三行排障,看清每一层报什么错
依次 ping 三个目标,注意每次报错文字的差别: 1.
ping 192.168.1.1—— 自家路由器,多半通(自家人一定理你) 2.ping 8.8.8.8—— 外网 IP,多半也通(说明出门没问题) 3.ping 一个不存在的域名(比如ping nosite-abc123.com)—— 报「找不到主机」第 3 条的错不是 ICMP 发的,是 DNS 层面的错(3.12 的 DNS 那件套)。
分清这一点很值钱:「找不到主机」= DNS 的事,「请求超时」/「无法访问」= 网络的事,处理方向完全不同。
- IP 既然是"尽力而为"的,为什么还需要 ICMP?
- ICMP 报文装在哪里?从 IP 首部的哪个字段能认出来?它算哪一层?
- ICMP 两大类报文分别是什么?各自的特点是什么?
- ICMP 差错报文发给谁?里面装着什么?为什么一定要装着那个东西?
- ICMP 会替你重传丢掉的包吗?
- 「类型 3 / 代码 4」是什么意思?它对应 3.4 里的哪句话?
- UDP 收不到回复时,能从哪里得到"没人在听"的线索?
- IPv6 下为什么不能一刀切禁掉 ICMP?
tracert某跳显示* * *,说明那台设备坏了吗?- 「找不到主机」和「请求超时」这两种报错,分别指向哪一层的问题?
答案:
① 因为 IP 不确认、不重传、不出声,发送方不知道出了什么事,就无法做任何反应。ICMP 专门承担"报信"这个职责。
② 装在 IP 包里,从 IP 首部的协议字段 = 1 能认出(6 是 TCP、17 是 UDP)。所以它归网际层。
③ 差错报告(类型 3 不可达 / 11 超时 / 12 参数问题 / 5 重定向),出了事才发、只有去程;询问(类型 8/0 回送 = ping、13/14 时间戳),主动发出、成对往返。
④ 回给原包的源地址(发件人)。里面装着原 IP 包的首部 + 前 8 字节数据。因为这 8 字节里含源端口和目的端口,发送方才能认出是哪条连接出了事——不带回去,它只知道"出错",不知道"哪个包错"。
⑤ 不会。ICMP 只报告不修复,重传是 TCP 的活(3.5),调整包大小是发送方自己的活。
⑥ 类型 3 = 终点不可达,代码 4 = 需要分片但 DF 置位——正是 3.4 Demo18 里 ping -f -l 1473 收到的那句话。
⑦ 来自 ICMP 类型 3 / 代码 3(端口不可达)。这是 UDP 唯一能拿到的反馈,但防火墙若连 ICMP 一起拦,这条线索也会断。
⑧ 因为 ICMPv6 承担了地址解析(邻居发现 NDP,取代 ARP)、路由器发现、地址自动配置等核心功能。一刀切拦掉会让网络直接瘫痪,正确做法是按类型放行。
⑨ 不是。* * * 只表示那台设备不回 ICMP,它照样在正常转发——后面的跳通就说明路是好的。
⑩ 「找不到主机」是 DNS 层面的错(名字没查成地址);「请求超时」/「无法访问目标主机」是网络层面的(前者=没回音,后者=收到 ICMP 差错报文)。
常见误区:
- ❌ "ping 不通就是网络断了" → 很多服务器和安全设备主动禁 ICMP(收 2.4)。ping 不通只能说明"它不理你",不等于"它不在"
- ❌ "ICMP 和 ping 是一回事" → ping 只是 ICMP 的一种用法(类型 8/0);ICMP 还有差错报告等一大家子
- ❌ "ICMP 能帮忙修复" → 只报告不修复。重传归 TCP、改包大小归发送方
- ❌ "ICMP 属于传输层" → 它装在 IP 包里(协议号 1),是网际层的成员
- ❌ "ICMP 只是拿来测试的" → 它是网络的基础设施:tracert、MTU 发现、UDP 端口不可达通知,全靠它
- ❌ "IPv6 下也应该禁 ICMP" → 绝对不能,ICMPv6 承担地址解析和自动配置,拦了网络就跑不起来
- ❌ "tracert 里的
* * *说明那台设备坏了" → 只是不回 ICMP,转发照做 - ❌ "差错报文会发给目标主机" → 回给源地址,因为目标根本没收到(收到了也帮不上忙)
九、下一步学什么
- ☑ 3.16 将IP地址与MAC地址对应(ARP) ✅ 已完成 —— 将IP地址与MAC地址对应(ARP):ICMP 报的是"包的下场",下一节讲的是"包在每一段该投给谁"——帧头那个 MAC 从哪来。
相关笔记
- 数据的发送和接收(IP、IP数据包、路由) —— "协议号 1 = ICMP" 与 "TTL 归零回 ICMP 超时" 的出处;本节把这两笔账收干净
- 收发数据时的规则(数据打包) —— Demo18 那句「需要分片但 DF 置位」,正式身份是 ICMP 类型 3 / 代码 4
- 负责传输数据的网络分层(网络接口层与网际层) —— "IP 尽力而为不补丢"这个坑,本节讲的是谁在旁边负责报告
- 为驱动应用程序而做准备的网络分层(传输层与应用层) —— UDP 没有确认机制,本节"端口不可达"是它唯一的反馈渠道
- 接收和传输数据的规则(使用TCP/IP进行通信) —— ICMP 只报告,真正重传的是 TCP 的超时重传
- 连接网络的过程(IP地址的设置) —— 三层递进排障法;本节把"每层报什么错"分得更细(DNS 错 vs ICMP 错)
- 组成网络(局域网的构建) —— "ping 不通先查防火墙",本节解释了为什么禁 ICMP 是常见做法
- 将IP地址与MAC地址对应(ARP) —— 同为"后勤"角色,但住处不同:ICMP 装在 IP 包里(协议号 1),ARP 直接装在以太网帧里;IPv6 下 ARP 的活也交给了 ICMPv6 的 NDP