[Python] 纯文本查看 复制代码 import socket
import struct
import time
import os
import sys
def calculate_checksum(data):
s = 0
for i in range(0, len(data), 2):
if i + 1 < len(data):
a = data
b = data[i + 1]
s += (a + (b << 8))
else:
s += data
s = (s >> 16) + (s & 0xffff)
s += s >> 16
return ~s & 0xffff
def create_icmp_packet(id, seq):
type = 8
code = 0
checksum = 0
identifier = id
sequence = seq
data = b'Hello, this is a ping packet.'
header = struct.pack('!BBHHH', type, code, checksum, identifier, sequence)
checksum = calculate_checksum(header + data)
header = struct.pack('!BBHHH', type, code, socket.htons(checksum), identifier, sequence)
return header + data
def ping(host, count=4):
try:
dest_addr = socket.gethostbyname(host)
except socket.gaierror:
print(f"无法解析主机名: {host}")
return
try:
if os.name == 'nt':
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
sock.settimeout(2)
except PermissionError:
print("运行此程序需要管理员/root权限")
return
pid = os.getpid() & 0xFFFF
sent_packets = 0
received_packets = 0
rtt_min = float('inf')
rtt_max = 0
rtt_sum = 0
print(f"正在Ping {host} [{dest_addr}] 具有 56(84) 字节的数据:")
for seq in range(count):
packet = create_icmp_packet(pid, seq)
sent_time = time.time()
try:
sock.sendto(packet, (dest_addr, 1))
sent_packets += 1
recv_packet, addr = sock.recvfrom(1024)
recv_time = time.time()
received_packets += 1
icmp_header = recv_packet[20:28]
icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq = struct.unpack('!BBHHH', icmp_header)
if icmp_type == 0 and icmp_id == pid:
rtt = (recv_time - sent_time) * 1000
rtt_min = min(rtt_min, rtt)
rtt_max = max(rtt_max, rtt)
rtt_sum += rtt
print(f"来自 {dest_addr} 的回复: 字节=56 时间={rtt:.2f}ms TTL=64")
except socket.timeout:
print("请求超时。")
except Exception as e:
print(f"发生错误: {e}")
sock.close()
print(f"\n{host} 的Ping统计信息:")
print(f" 数据包: 已发送 = {sent_packets}, 已接收 = {received_packets}, 丢失 = {sent_packets - received_packets} ({(sent_packets - received_packets)/sent_packets*100:.1f}% 丢失),")
if received_packets > 0:
print("往返行程的估计时间(以毫秒为单位):")
print(f" 最短 = {rtt_min:.2f}ms, 最长 = {rtt_max:.2f}ms, 平均 = {rtt_sum/received_packets:.2f}ms")
if __name__ == "__main__":
if len(sys.argv) > 1:
target = sys.argv[1]
else:
target = input("请输入要Ping的主机名或IP地址或者服务器IP: ")
ping(target)
|