网络通信过程中可能出现各种各样的差错,因此需要具备 差错传送 机制。开始介绍解决方案前,我们先考察一下问题的背景:
这是我们在网络规划一节讨论的某公司网络拓扑图,法务部同事 alice 的 IP 地址是 192.168.170.194/26 ,她准备向研发部的 bruce 发送一些数据,bruce 的 IP 地址是 192.168.171.3/25 。
由于 bruce 今天刚好休假,电脑没开机,这时会发生什么事情呢?
alice 发出来的 IP 包,可以顺利到达研发部路由器。路由器接到包后,一看目标网络就在网卡 eth1 上,它可以直接通过以太网帧将包发送至目的地。
为了封装以太网帧,路由器需要先找到 192.168.171.3 的 MAC 地址——向研发部网络广播 ARP 地址解析请求。但由于 bruce 的电脑已经关机,它无法应答路由器的 ARP 请求。
由于久久得不到 ARP 应答,路由器便认为 192.168.171.3 这个地址 不可达 。接下来,路由器需要将这个情况反馈给 alice ,即 192.168.170.194 。具体怎么做呢?
解决方案很简单,路由器可以封装一个 IP 包,将差错信息作为数据发给 alice :
整个网络所有参与方需要对差错信息的组织格式达成一致,这就是 ICMP 协议负责的范畴。
ICMP 报文结构
互联网控制消息协议 ( Internet Control Message Protocol )简称 ICMP ,是 IP 的辅助协议,同样位于网络层,负责网际通信中 控制信息 和 差错信息 的传送。
ICMP 有赖 IP 提供的网际通信能力,它的报文作为数据承载在 IP 包中进行传输:
注意到,IP 包头部中的 protocol 字段,用于标识数据部分所属的协议,可以当做数据类型来理解。如果 protocol 字段的值为 1 ,说明 IP 包的数据部分是一个 ICMP 报文。
那么,ICMP 报文的格式又长啥样呢?
ICMP 报文同样分为 头部 和 数据 两部分,其中头部字段如下:
- 类型 ( type ),顾名思义用来标识 ICMP 报文的类型,例如 目的不可达 ( destination unreachable )差错报文;
- 代码 ( code ),进一步划分 ICMP 报文的类型,标识错误的原因,例如目的不可达可以进一步分成网络不可达、主机不可达以及端口不可达等等;
- 校验和 ( checksum ),用于差错校验,由 ICMP 头部计算得出;
常见的 ICMP 报文类型列举如下表:
类型 | 描述 | 状态 | 查询 | 差错 |
---|---|---|---|---|
0 | 回显响应 | ✔️ | ||
1 | 保留 | 未分配 | ||
2 | 保留 | 未分配 | ||
3 | 目的不可达 | ✔️ | ||
4 | 源端关闭 | 弃用 | ✔️ | |
5 | 重定向 | ✔️ | ||
6 | 备用主机地址 | 弃用 | ||
7 | 保留 | 未分配 | ||
8 | 回显请求 | ✔️ | ||
9 | 路由通告 | ✔️ | ||
10 | 路由请求 | ✔️ | ||
11 | 超时错误 | ✔️ | ||
12 | 参数错误(IP头部错误) | ✔️ | ||
13 | 时间戳请求 | ✔️ | ||
14 | 时间戳应答 | ✔️ | ||
… |
注意到,ICMP 报文类型分为两种,一种是差错传送,一种是信息查询。举个例子,类型 13 用于向一台主机查询时间戳。下一小节,我们将研究 ping 命令,它是利用 请求回显 实现的,这也是一种查询类型。
主机不可达差错
回到前面的场景,研发部路由器发现 192.168.171.3 ( bruce )不可达后,将向 192.168.170.194 ( alice )传送主机不可达差错。差错消息用 ICMP 报文封装,其中类型为 3 ,代表目的地不可达;代码为 1 ,代表主机不可达。
由于 192.168.170.194 ( alice )可能同时与多方通信,因此 ICMP 报文必须提供更多上下文,表明是 192.168.171.3 ( bruce )不可达。
问题不难解决,将产生差错的 IP 包,作为 ICMP 报文的数据,一并发给 192.168.170.194 ( alice )不就好了吗?实际上,不用将整个 IP 包都附上,只需附上 IP 包头部以及数据的前 8 字节即可。
最终,ICMP 包被封装成 IP 包,由研发部路由器发给 alice ,其中源地址是路由器的地址,即 192.168.170.5 ;目的地址为 alice 的地址,即 192.168.170.194 ;协议类型为 1 ,代表 ICMP 协议。详情如下:
192.168.170.194 ( alice )收到 ICMP 报文后,检查类型和代码字段,就知道这是一个主机不可达错误。它继续检查附在 ICMP 报文数据中的差错包头部,就知道是发数据给 bruce 时产生的。
顺便提一下,额外附上差错包数据的前 8 字节的原因在于:IP 报文数据经常承载传输层的协议分组,前 8 个字节刚好是分组的头部。有了差错包的传输层分组头部,则可以进一步确定差错是访问目标主机的什么端口产生的。
扩展阅读
【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: