为什么说 ICMP 协议是网络最强辅助?
今天咱们说说 ICMP 协议。ICMP 可谓是网络世界中的最强辅助了,IP 数据包如果在途中遭遇不测的话,全靠 ICMP 来通知,要不然丢掉的 IP 数据包就有如石沉大海,从此杳无音信,发送方也不知道这个包有没有传输成功,倘若没有成功,那失败原因是什么?这些,全靠 ICMP 协议来通知。
ICMP 全称互联网控制报文协议(Internet Cntrol Message Protocol),是网络层的重要协议。
ICMP 是干啥用的?
它到底是用来干啥的呢?为啥叫控制报文协议,控制的是什么?
ICMP 分为查询报文和差错报文两大类。查询报文是我们主动发起的,比如 ping 命令;而差错报文是在发生差错之后要发给源端的,这都是互联网协议模型约定好的。
ICMP 的差错报文反馈发生在通信环境中的遇到的各种问题。通过这些信息,使管理者可以对所发生的问题作出诊断,然后采取适当的措施解决。
ICMP 的差错报文是整个数据传输链路中非常重要的一个环节。打个比喻,差错报文就是一个只报告坏消息的信使,当数据包在网络中一路畅通的时候,ICMP 差错报文就像隐身了一样,你根本不会知道它的存在,一旦数据包在网络中碰到了各种各样的障碍,这个信使就出来活动了,它的目的只有一个,就是把这个数据包遭遇的不测通知给发送端,但是话术就那么 20 多种(对应差错代码)。
比如下面两个场景,想必你也有点熟悉吧。
当路由器收到一份 IP 数据报但又不能转发时,就要发送一份 ICMP「主机不可达」差错报文。
当 IP 数据报应该被发送到另一个路由器时,收到数据报的路由器就要发送 ICMP「重定向」差错报文给 IP 数据报的发送端。
ICMP 协议说明
虽然工作在网络层,看上去和 IP 协议是并列的,但是 ICMP 报文要附加 IP 头,一般被 IP 层或者更高层的协议(例如 TCP 或 UDP)使用。很少有应用程序直接使用 ICMP 协议,除了 ping
、traceroute
。
ICMP 协议格式
ICMP 协议格式和 IP 协议、TCP 协议这些比起来,那还是非常简单的。
类型
类型字段占用 8 位,主要定义报文的大类,比如类型为 3 统一表示的是不可达
,而具体原因是什么则要由代码字段决定。
代码
代码字段同样占用 8 位,代码字段其实就是类型下的子类型,比如上面说了类型为 3 是不可达,代码为 0 表示网络不可达,代码为 1 表示主机不可达。
检验和
用于错误检查,和 IP 协议的检验和的作用一致。
内容
因为类型和代码不同,表示产生差错的原因不同,不同的原因都要有对应的描述,内容这部分就是用来描述产生差错的原因的。
接下来会举几个例子说明。
下面这张图是 ICMP 的分类,包括查询报文和差错报文,需要原始 Excel 的同学可以回复 ICMP
获取源文件。
目的不可达差错报文
目的不可达是网络传输中经常遇到的问题,各位在开发的过程中可能也碰到过,尤其是做网络编程的时候,经常会碰到,比如连错 IP 了,比如端口设置错了。
通过上表可知,当类型为 3 的时候,都是不可达的错误,而代码可以从 0 -15,也就是说有 16 种不可达的具体原因。这种情况下的协议格式是下面这样的。
类型为 3 ,代码 0 - 15。检验和后面有 4 个字节的空间是不使用的,但是必须为 0 ,没理由,就这样。
前面说到了内容部分是根据类型和代码不同而不同的。如果是目的不可达,也就是类型是 3 的情况下,内容分为两部分,IP 首部和原始 IP 数据报中数据部分的前 8 个字节。
原始 IP 数据报中数据部分指的就是 TCP 或者 UDP 这些网络层之上的协议,拿 TCP 来说,TCP 是传输层的,当 TCP 数据报到达网络层,会加上 IP 首部,变成一个 IP 数据包。所以这里说的数据部分就是 TCP 数据报,但是这个数据报可能很大,所以只用前 8 个字节就够了,因为前 8 个字节包含的信息已经足够用了。
回想一下 TCP 协议的格式,前 8 个字节就是下图红框部分,包含源端口和目的端口以及序号。
例如代码为 3 的时候,差错信息是端口不可达,那有了 TCP 协议的前 8 个字节就能知道导致这个错误的原始数据报文中的目的端口是多少,不可达的端口也就是这个端口。也可以知道原始报文的源端口是多少,有了源端口号就知道这个数据包是哪个用户进程发出来的,就可以交给这个进程对这个差错及时进行处理了。
源端口号是关联用户进程的重要标示,比如我们开发了一个应用,这个应用占用了 8888 和 8898 两个端口,如果安装了这个应用的机器收到了一个差错报文,而差错报文中的内容部分的原始数据包前 8 个字节拆解后,发现源端口是 8898,那就知道这个要交给我们开发的这个应用去处理了。
下面是一个端口不可达的差错报文,用 WireSharek 监测到的格式。
telnet 一个没有开放的端口即可获得 ICMP 端口不可达的差错报文。
查询报文
将 ICMP 用作查询报文的场景比较少,用作查询报文的意思就像是使用 ARP 协议或者 TCP 协议这种,是我们主动发起的,只不过选了 ICMP 协议。
比如 ping
和 traceroute
这两个,之后我们再讲,这两个比较有意思,对 ICMP 应用很巧妙。
另外,可以用作无盘系统启动过程中来获取自身的子网掩码。还可以用作向第三方系统查询当前的时间戳。
了解一下就可以了。
有一些场景不发送差错报文
有些场景下是不发送差错报文的,这样做的目的是为了防止 ICMP 差错报文带来广播风暴。
ICMP 差错报文本身发生差错,是不会对差错报文再发送差错报文的。是不是读起来有点绕,TCP 、UDP 出错会发送差错报文,但是 ICMP 差错报文在通知源端的过程出错了,那就不管了,要不然可能就没玩没了的发了,比如源端的网线断了。但是, ICMP 查询报文可能会产生 ICMP 差错报文,比如 ping 命令在传输过程中出错了,源端会收到差错报文。
目的地址是广播地址或多播地址(D 类地址)的 IP 数据报,不发送差错报文。
作为链路层广播的数据报,不发送差错报文,ARP 就是典型的链路层广播数据报。
不是 IP 分片的第一片,不发送差错报文。数据如果过长,网络层是会进行分片的,这些分片实际上还是同一个数据包的,这种情况下只对第一片发送差错报文,其他分片不管。
源地址不是单个主机的数据报,不发送差错报文。 源地址不能为零地址、环回地址、广播地址或多播地址。
总结
1、 ICMP 在网络层,但要加上 IP 首部;
2、ICMP 分为查询报文和差错报文,主要用到的还是差错报文;
3、ICMP 的差错报文就好像一个只通知坏消息的信息,当数据报在网络中出现问题的时候,及时告知源端,告知的内容包括原因以及产生错误的原始数据报的必要部分;
4、有一些情况是不会发送 ICMP 差错报文的,这样做是为了防止网络风暴;
版权声明: 本文为 InfoQ 作者【互联网工科生】的原创文章。
原文链接:【http://xie.infoq.cn/article/5cf1e1c7a2d52a77eef60223e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论