ping 是一种因特网包探索器,用于测试网络连接量的程序,Ping是工作在TCP/IP网络体系结构中应用层的一个服务命令,主要是向特定的目的主机发送 ICMP 请求报文,测试目的站是否可达及了解其有关状态,实现Ping方法的这段代码原始版本来源于网络,后经排版封装后实现了一些功能,放在这里收藏之用。

第一步封装MyPing类,在pycharm下面创建一个MyPing.py文件,详细代码备注如下。

import time, struct
import socket, select class MyPing():
# 发送原始套接字
def raw_socket(self, dst_addr, imcp_packet):
rawsocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
send_request_ping_time = time.time()
rawsocket.sendto(imcp_packet, (dst_addr, 80))
return send_request_ping_time, rawsocket # 计算校验和
def chesksum(self, data):
n = len(data)
m = n % 2
sum = 0
for i in range(0, n - m, 2):
sum += (data[i]) + ((data[i + 1]) << 8)
sum = (sum >> 16) + (sum & 0xffff)
if m:
sum += (data[-1])
sum = (sum >> 16) + (sum & 0xffff)
answer = ~sum & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer # 通过域名获取主机地址
def get_host_address(self,host):
dst_addr = socket.gethostbyname(host)
return dst_addr # 接受到数据包
def request_ping(self, data_type, data_code, data_checksum, data_ID, data_Sequence, payload_body):
# 把字节打包成二进制数据
imcp_packet = struct.pack('>BBHHH32s', data_type, data_code, data_checksum, data_ID, data_Sequence,payload_body)
# 获取校验和
icmp_chesksum = self.chesksum(imcp_packet)
# 把校验和传入,再次打包
imcp_packet = struct.pack('>BBHHH32s', data_type, data_code, icmp_chesksum, data_ID, data_Sequence,payload_body)
return imcp_packet # 相应数据包,解包执行
def reply_ping(self, send_request_ping_time, rawsocket, data_Sequence, timeout=3):
while True:
# 实例化select对象(非阻塞),可读,可写为空,异常为空,超时时间
what_ready = select.select([rawsocket], [], [], timeout)
# 等待时间 wait_for_time = (time.time() - started_select)
wait_for_time = (time.time() - send_request_ping_time)
# 没有返回可读的内容,判断超时
if what_ready[0] == []:
return -1
# 记录接收时间
time_received = time.time()
# 设置接收的包的字节为1024
received_packet, addr = rawsocket.recvfrom(1024)
# 获取接收包的icmp头
icmpHeader = received_packet[20:28]
# 反转编码
type, code, r_checksum, packet_id, sequence = struct.unpack(">BBHHH", icmpHeader)
if type == 0 and sequence == data_Sequence:
return time_received - send_request_ping_time
# 数据包的超时时间判断
timeout = timeout - wait_for_time
if timeout <= 0:
return -1 # 向特定地址发送一条ping命令
def send_ping(self, address):
data_type = 8
data_code = 0
data_checksum = 0
data_ID = 0
data_Sequence = 1
payload_body = b'abcdefghijklmnopqrstuvwabcdefghi' # 请求ping数据包的二进制转换
icmp_packet = self.request_ping(data_type, data_code, data_checksum, data_ID, data_Sequence, payload_body)
# 连接套接字,并将数据发送到套接字
send_request_ping_time, rawsocket = self.raw_socket(address, icmp_packet)
# 数据包传输时间
times = self.reply_ping(send_request_ping_time, rawsocket, data_Sequence)
if times > 0:
return_time = int(times * 1000)
return return_time
else:
return -1

实现模仿Windows中的ping命令,代码如下:

from MyPing import *

if __name__ == '__main__':
# 使用Ping方法
host = "www.lyshark.com"
ping = MyPing() sumtime, shorttime, longtime, avgtime = 0, 1000, 0, 0
# 8回射请求 11超时 0回射应答
data_type = 8
data_code = 0
# 检验和
data_checksum = 0
# ID
data_ID = 0
# 序号
data_Sequence = 1
# 可选的内容
payload_body = b'abcdefghijklmnopqrstuvwabcdefghi'
dst_addr = socket.gethostbyname(host)
print("正在 Ping {0} [{1}] 具有 32 字节的数据:".format(host, dst_addr))
# 发送3次
for i in range(0, 3):
# 请求ping数据包的二进制转换
icmp_packet = ping.request_ping(data_type, data_code, data_checksum, data_ID, data_Sequence + i, payload_body)
# 连接套接字,并将数据发送到套接字
send_request_ping_time, rawsocket = ping.raw_socket(dst_addr, icmp_packet)
# 数据包传输时间
times = ping.reply_ping(send_request_ping_time, rawsocket, data_Sequence + i)
if times > 0:
print("来自 {0} 的回复: 字节=32 时间={1}ms".format(dst_addr, int(times * 1000)))
return_time = int(times * 1000)
sumtime += return_time
if return_time > longtime:
longtime = return_time
if return_time < shorttime:
shorttime = return_time
time.sleep(0.7)
else:
print("请求超时")

运行效果如下:

发送一条ping探测命令,send_ping()主要用于发送一个Ping包,后期我们可以实现一个主机存活探测器,主要调用代码如下:

from MyPing import *

if __name__ == "__main__":
# 使用Ping方法
ping = MyPing() address = ping.get_host_address("www.lyshark.com")
print("域名地址: {}".format(address)) # 对单台主机Ping
ref = ping.send_ping(address)
if( ref != -1):
print("已经连通, 抖动值: {}".format(ref))

输出测试效果如下:

如上我们就可以实现对特定主机执行Ping检测了,接下来我们开始编写一个能够计算出特定范围内主机数的CalculationIP()方法,并通过开线程实现一个批量主机存活探测器.

from MyPing import *

def CalculationIP(Addr_Count):
ret = []
try:
IP_Start = str(Addr_Count.split("/")[0]).split(".")
IP_Heads = str(IP_Start[0] + "." + IP_Start[1] + "." + IP_Start[2] +".")
IP_Start_Range = int(Addr_Count.split(".")[3].split("/")[0])
IP_End_Range = int(Addr_Count.split("/")[1])
for item in range(IP_Start_Range,IP_End_Range+1):
ret.append(IP_Heads+str(item))
return ret
except Exception:
return 0 if __name__ == "__main__":
ret = CalculationIP("192.168.1.1/254") for each in ret:
ping = MyPing()
ref = ping.send_ping(each)
print("地址: {} ---> 抖动值: {}".format(each,ref))

输出效果如下:

参考文献:https://blog.csdn.net/Small_Teenager/article/details/122123299

Python 实现Ping命令状态检测的更多相关文章

  1. python MySQL-Slave从服务器状态检测脚本

    #!/bin/bash mysql -e "show slave status\G" > mysql_status.txt array=($(egrep 'Slave_IO_ ...

  2. [小菜随笔]python tkinter实现简单的ping命令

    本文主要是介绍python图形界面上的按键与实际功能的对接,其实编程掌握了基础之后的学习应该都是靠自己去挖掘其他的 在网上发现多半教程都是2的,故本文使用的是python3.5,其实也没什么区别,就有 ...

  3. 【问题解决方案】从 Anaconda Prompt 或 Jupyter Notebook 终端进入Python后重新退出到命令状态

    从 Anaconda Prompt 或 Jupyter Notebook 终端进入Python后重新退出到命令状态 退出Python:exit() 或者 Ctrl+z 例子一枚 默认打开的是3.7,需 ...

  4. Linux分享笔记:系统状态检测命令小结

    作为一名合格的运维人员,要能很好地了解Linux服务器,要能熟练查看Linux系统的运行状态.以下是常用到的Linux系统状态检测命令. 1. ifconfig:用于获取网卡配置与网络状态等信息.通常 ...

  5. ping命令脚本实现显示网络状态、学生姓名、学号

    #!/bin/bash a=. ####定义一个固定变量 h=(wanghao xieyunshen 刘桃) ####定义数组 ..} ####for循环,后面的in是条件即从多少循环到多少 do # ...

  6. 每天一个linux命令(54):ping命令

    Linux系统的ping命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地址192.168.1.1试试”. ...

  7. PING命令入门详解

    转自:http://www.linkwan.com/gb/tech/htm/928.htm 1.Ping的基础知识 ping命令相信大家已经再熟悉不过了,但是能把ping的功能发挥到最大的人却并不是很 ...

  8. python脚本实现集群检测和管理

    python脚本实现集群检测和管理 场景是这样的:一个生产机房,会有很多的测试机器和生产机器(也就是30台左右吧),由于管理较为混乱导致了哪台机器有人用.哪台机器没人用都不清楚,从而产生了一个想法-- ...

  9. 每天一个linux命令(46):ping命令

    Linux系统的ping 命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地 址192.168.1.1试试 ...

  10. Linux中ping命令

    Linux系统的ping命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地址192.168.1.1试试”. ...

随机推荐

  1. 使用 std::string_view 提升字符串处理性能

    C++标准库提供了一个非常优秀的字符串处理类std::string,我们可以通过该类完成各种字符串操作.但是std::string有一个缺点,它的很多操作都是针对字符串实体,存在不必要的内存拷贝的代码 ...

  2. VS遇到 error C4996问题的解决方法

    在编译c++程序时报如下错: error C4996: 'strncat': This function or variable may be unsafe. Consider using strnc ...

  3. Codeforces Round #728 (Div. 2) A~C 补题记录

    比赛链接:Here 1541A. Pretty Permutations 给定 \(1,2,3,4,...n\) 序列,让每一个数字都不处于原来的位置,但总的移动距离要最小 \(n\) 为偶数的情况 ...

  4. 【每日一题】40. 旅游 (树形DP解决树的最大独立集)

    补题链接:Here 算法涉及:树形DP寻找树上最大独立集 一开始想到是利用 树形DP 找树的直径问题,但这里由于可以利用走过的点衍生,所以不符合树的直径问题 查询了一下资料这道题是属于: 树的最大独立 ...

  5. 在wsl2 kali发行版中安装docker

    前言 因为不想开虚拟机,而又需要多个linux发行版来做测试,也不想使用docker-desktop来曲线救国,所以想直接安装个docker随时使用,这一路也是踩了不少坑.直接复制进终端进行安装 su ...

  6. Threejs实现一个园区

    一.实现方案 单独贴代码可能容易混乱,所以这里只讲实现思路,代码放在最后汇总了下. 想要实现一个简单的工业园区.主要包含的内容是一个大楼.左右两片停车位.四条道路以及多个可在道路上随机移动的车辆.遇到 ...

  7. 开发人员常用Docker指令

    什么是 Docker? Docker 是一个开源的容器化平台,用于构建.打包和运行应用程序.它允许开发者将应用程序及其依赖项打包成一个独立的可移植容器,可以在任何环境中运行,无论是开发环境.测试环境还 ...

  8. BFS 广搜

    HDU 2612 #include<stdio.h> #include<string.h> #include<iostream> #include<queue ...

  9. BTC-协议

    BTC-协议 一个去中心化的数字货币要解决两个问题 1.谁有权发行货币 比特币的发行是由挖矿决定的(coinbase transaction 唯一一个产生新币的途径)比特币通过挖矿来决定货币的发行权, ...

  10. Tmux | 常用操作存档

    (因为自己实在是太好忘了,所以在博客存档方便查找) 参考资料:Tmux 使用教程 | 阮一峰的网络日志 tmux new -s <session-name> <Ctrl+B D> ...