Ping原理,以及Go实现一个简单的Ping

原文地址

前言

我们在判断本地网络是否畅通、网络延迟、是否丢包等,除了通过浏览器是否能访问一个网页来判断,还经常会通过终端的 Ping 来判断是否畅通,例如这样:

Ping 名字由来是源于声纳在探测时发出的声音。

那么 Ping 到底是如何工作的呢?

关于 Ping 的工作原理

在介绍 Ping 之前,首先需要介绍一下 TCP/IP 的参考模型,即应用层、传输层、网际互联层(网络层)、网络接入层(主机-网络层)。其中的网络层主要负责主机到主机的通信,在网络层的协议中,我们最先想到的就是 IP 协议,其实网络层还有一个比较重要的协议 ICMP (互联网控制报文协议 Internet Control Message Protocol),而 Ping 程序就是基于 ICMP 工作的。

当然网络层还有其它较为重要的的协议(IGMP),感兴趣可以自行查看,其它协议不在本篇文章的讨论范围内,嘿嘿

ICMP

在网络中的作用

在网络世界中,各种传输是非常复杂的,那么在这种复杂的环境中传输网络包,可能会经常遇到问题,例如网络不可达、主机不可达、超时等等一系列的问题, 当遇到问题时那该怎么办呢,直接销毁?那客户端可不清楚发生了什么,这时需要告知该客户端传出的消息遇到了什么问题,这样就可以帮助客户端调整传输策略。

在上面举了一个 ICMP 的回报机制,还有一个非常重要的功能,即侦测,目的就是让我们能够检测网络的连接状况,确保连接的准确性。

从上面看 ICMP 协议在网络中是不是必不可少也是非常非常重要的一个协议哈哈哈哈。

ICMP 报文格式

所有 ICMP 报文的前 4 个字节都是一样的,但是剩下的其他字节则不相同。类型字段可以有 15 个不同的值,以描述特定类型的 ICMP 报文,某些 ICMP 报文还使用代码字段的值来进一步描述不同的条件。

检验和字段覆盖整个 ICMP 报文(该字段起校验的作用,防止伪造数据)。

ICMP 报文的类型

下面的表中列举除了各种类型的 ICMP 报文,不同类型由报文中的类型字段和代码字段来共同决定。

类型 代码 描述 查询 差错
0 0 回显应答(Ping 应答) ·
3 - 目的不可达 ·
4 0 源端被关闭 ·
5 - 重定向 ·
8 0 请求回显(Ping 回应) ·
9 0 路由器通告 ·
10 0 路由器请求 ·
11 - 超时 ·
12 - 参数问题 ·
13 0 时间戳请求 ·
14 0 时间戳应答 ·
15 0 信息请求 ·
16 0 信息应答 ·
17 0 地址掩码请求 ·
18 0 地址掩码应答 ·

表中的最后两列表明 ICMP 报文是一份查询报文还是一份差错报文,因为对 ICMP 差错报文有时需要特殊处理,因此需要对它们进行区分。

当发送一份 ICMP 差错报文时,报文始终包含 IP 的首部和产生 ICMP 差错报文的 IP 数据报的前 8 个字节。这样,接收 ICMP 差错报文的模块就会把它与某个特定的协议和用户进程联系起来。

Ping 程序主要用到的类型有 0、8 即回显应答和请求回显。

与其他报文间的关系

ICMP 通常被认为时 IP 层的组成部分,它传递差错报文以及其他需要注意的信息,ICMP 通常被 IP 层或更高层协议使用,例如 ICMPIP 数据报内部被传递

通过抓包查看 Ping 过程

可以使用 Wireshark 抓包工具进行抓包。

在终端中执行 ping blog.sayhe110.cn

在 Wireshark 中可以看到请求以及应答,可以看到每个请求的响应与应答都是一对一的,请求的类型是 8(请求回显),响应的类型是 0(回显应答)。

在执行完后,突然有一个发出的请求(不是我操作的情况下),响应了个网络不可达的请求 ,具体信息即网络端口不可达 (真是意外的惊喜哈哈哈哈哈,正好可以看一下异常场景的响应类型以及代码)

使用 Go 实现一个简单的 Ping 程序(EasyPing)

在了解完 Ping 是基于 ICMP 协议实现的后,那我们同样也可以实现一个简单的 Ping 程序,这里选用 Go 是因为最近在学习 Go ,就当做练手的项目了,当然有兴趣的也可以用其他语言实现哈哈哈哈。

因为篇幅有限,大家可以直接去看完整的源代码(有任何问题欢迎提 issue) github.com/SayHe110/ea… Star !!!求求大家给个 Star 吧 🙁

总结

ICMP 处于网络层,负责进行网络的侦测,以及对发出的请求返回的信息带回,其中利用了类型(Type)、代码(Code)进行区分不同的 ICMP 报文。Ping 程序是典型的基于 ICMP 协议实现的程序。

参考

  • TCP/IP 详解卷 1