解析ping原理及实现

您所在的位置:网站首页 ping命令的方法 解析ping原理及实现

解析ping原理及实现

2023-03-12 17:35| 来源: 网络整理| 查看: 265

PING 一、概述

ping属于一个通信协议,是TCP/IP协议的一部分。利用“ping”命令可以检查网络是否通畅或者网络连接速度,很好地分析和判定网络故障。

Ping发送一个ICMP(Internet Control Messages Protocol),即因特网信报控制协议;接收端回声消息给目的地并报告是否收到所希望的ICMPecho (ICMP回声应答)。它的原理是:利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,通过对方回复的数据包来确定两台网络机器是否连接相通,时延是多少。

ping是端对端连通,通常用来作为可用性的检查,但是某些病毒木马会强行远程执行大量ping命令抢占你的网络资源,导致系统变慢,网速变慢。严禁ping入侵作为大多数防火墙的一个基本功能提供给用户进行选择。通常的情况下你如果不用作服务器或者进行网络测试,可以放心的选中它,保护你的电脑。

二、ICMP概述 定位

ping属于哪一层?ping命令使用的tcp报文还是udp报文呢?

首先,答案是:PING是应用层直接使用网络层ICMP的一个例子,它没有通过运输层的TCP或UDP。

PING命令是我们能够直接使用的命令,像HTTP、FTP,属于应用层。ping命令底层使用的是ICMP,ICMP报文封装在ip包里,所以ICMP属于网络层协议。

分层协议 补充IGMP(是G)

IGMP即Internet工作组管理协议(Internet Group Management Protocol),IGMP主要用来解决网络上广播时占用带宽的问题。

当网络上的信息要传输给所有工作站时,就发出广播(broadcast)信息(即IP地址主机标识位全为1),交换机会将广播信息不经过滤地发给所有工作站;但当这些信息只需传输给某一部分工作站时,通常采用组播(multicast,也称多点广播)的方式,这就要求交换机支持IGMP。支持IGMP的交换机会识别组播信息并将其转发至相应的组,从而使不需要这些信息的工作站的网络带宽不被浪费。IGMP对于提高多媒体传输时的网络性能尤为重要。

IP和ICMP报文的关系

报文内的具体字段可以暂时抛开,可以看到ICMP报文是内嵌在IP报文内的,也就是说IP报文里包含着ICMP报文,ICMP报文是IP报文的一部分。

IP和ICMP报文 三、ICMP实现

由于PING命令是使用ICMP实现的,那么ICMP是如何实现的对了解PING是至关重要的。

1. ICMP报文类型

ICMP类型分为两大类:

差错报告 询问报告

ICMP通过一个整数数字来表示不同的报文类型,双方通过该类型值来识别报文的目的,并作出不同的反应。

种类 类型值 ICMP报文的类型 差错报告 3 终点不可达 差错报告 11 时间超过 差错报告 12 参数问题 差错报告 5 改变路由 询问报告 8/0 回送请求/回答 询问报告 13/14 时间戳请求/回答

对于PING命令,我们需要的到达的效果是检查是否联通。那么只需要我们的请求方带上数字标识8(回送请求),如果对方回送的数值是0,那么证明两者是联通的。

2. Checksum 检验和

校验和是一个从数据包计算出来的值来检查其完整性。通过完整性,我们可以检查收到的数据是否没有错误。由于最底层的网络通信是通过电路传输的,期间包含很多不定因素,可能导致部分数据丢失、改变。所以网络协议大都需要通过某种方法来确保收到的数据是正确的。检验和是常用的一种方式。

ICMP协议中使用了检验和来保证接收到正确的数据。在源端,计算校验和并将其作为字段设置在报文中。在目标端,再次计算校验和,并用报文中现有的校验和值进行交叉检查,看看数据包是否正常。

如何计算

icmp检验和的计算与IP检验和类似,不同的是,icmp需要通过其报文信息与数据主体一起校验,IP只需校验头部信息。

因为通常在IP报头之后的数据(如ICMP,TCP等)具有自己的校验和

就算法而言,imcp校验和是:imcp报文中所有16位字的补码总和的16位补码。具体操作如:

将校验和字段置为0。 将每两个字节(16位)相加(二进制求和)直到最后得出结果,若出现最后还剩一个字节继续与前面结果相加。 (溢出)将高16位与低16位相加,直到高16位为0为止。 将最后的结果(二进制)取反。

关于二进制求和:

# 例: # 1. 不溢出时 4500 - > 0100 0101 0000 0000 003c - > 0000 0000 0011 1100 453C - > 0100 0101 0011 1100 # 结果 # 2. 溢出时 高16位与低16位相加 E188 - > 1110 0001 1000 1000 AC10 - > 1010 1100 0001 0000 18D98->1 1000 1101 1001 1000 8D99 - > 1000 1101 1001 1001 # 结果 # 最后结果取反 0A0C - > 0000101000001100 # 最后一次累加 4E19 - > 0100111000011001 # 取反得最终结果 代码实现 # 检验和 def chesksum(data): n = len(data) m = n % 2 sum = 0 for i in range(0, n - m, 2): # 传入data以每两个字节(十六进制)通过ord转十进制,第一字节在低位,第二个字节在高位 # ?????为什么第二个字节在高位 sum += (data[i]) + ((data[i+1]) > 16) + (sum & 0xffff) if m: sum += (data[-1]) sum = (sum >> 16) + (sum & 0xffff) # 取反 answer = ~sum & 0xffff # 主机字节序转网络字节序列 answer = answer >> 8 | (answer 16) + (sum & 0xffff) if m: sum += (data[-1]) sum = (sum >> 16) + (sum & 0xffff) # 取反 answer = ~sum & 0xffff # 主机字节序转网络字节序列 answer = answer >> 8 | (answer longtime: longtime = return_time if return_time < shorttime: shorttime = return_time time.sleep(0.7) else: lost += 1 print("请求超时。") if send == 4: print("{0}的Ping统计信息:".format(dst_addr)) print("\t数据包:已发送={0},接收={1},丢失={2}({3}%丢失),\n往返行程的估计时间(以毫秒为单位):\n\t最短={4}ms,最长={5}ms,平均={6}ms".format( i + 1, accept, i + 1 - accept, (i + 1 - accept) / (i + 1) * 100, shorttime, longtime, sumtime/send)) if __name__ == "__main__": i = input("请输入要ping的主机或域名\n") ping(i) 补充:SOCK_RAW

实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM)。而这些数据包都是由系统提供的协议栈实现,用户只需要填充应用层报文即可,由系统完成底层报文头的填充并发送。

然而在某些情况下需要执行更底层的操作,比如修改报文头、避开系统协议栈等。这个时候就需要使用其他的方式来实现。

原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM、SOCK_DGRAM的套接字,它实现于系统核心。首先来说,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。总体来说,SOCK_RAW可以处理普通的网络报文之外,还可以处理一些特殊协议报文以及操作IP层及其以上的数据。

引用自: https://blog.csdn.net/zhj082/article/details/80531628 https://www.jianshu.com/p/17f16256008d 《计算机网络》第七版 https://blog.csdn.net/newnewman80/article/details/8000404


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3