1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| from socket import * import os import sys import struct import time import select import binascii ICMP_ECHO_REQUEST = 8 def checksum(strr): csum = 0 countTo = (len(strr) / 2) * 2 count = 0 while count < countTo: thisVal = strr[count+1] * 256 + strr[count] csum = csum + thisVal csum = csum & 0xffffffff count = count + 2 if countTo < len(strr): csum = csum + str[len(strr) - 1] csum = csum & 0xffffffff csum = (csum >> 16) + (csum & 0xffff) csum = csum + (csum >> 16) answer = ~csum answer = answer & 0xffff answer = answer >> 8 | (answer << 8 & 0xff00) return answer
def receiveOnePing(mySocket, ID, timeout, destAddr): timeLeft = timeout while 1: startedSelect = time.time() whatReady = select.select([mySocket], [], [], timeLeft) howLongInSelect = (time.time() - startedSelect) if whatReady[0] == []: return "请求超时。" timeReceived = time.time() recPacket, addr = mySocket.recvfrom(1024) t, c, checksum, recID, seq = struct.unpack("bbHHh", recPacket[20:28]) ttl, = struct.unpack("b", recPacket[8:9]) if t == 3: if c == 0: return "Destination Network Unreachable." elif c == 1: return "Destination Host Unreachable." if t != 0 or c != 0 or recID != ID or seq != 1: return "Recieve error." timeLeft = timeLeft - howLongInSelect if timeLeft <= 0: return "请求超时。" return [1-timeLeft, ttl, len(recPacket)]
def sendOnePing(mySocket, destAddr, ID): myChecksum = 0 header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) data = struct.pack("d", time.time()) myChecksum = checksum(header + data) if sys.platform == 'darwin': myChecksum = htons(myChecksum) & 0xffff else: myChecksum = htons(myChecksum) header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) packet = header + data mySocket.sendto(packet, (destAddr, 1))
def doOnePing(destAddr, timeout): icmp = getprotobyname("icmp") mySocket = socket(AF_INET, SOCK_RAW, icmp) myID = os.getpid() & 0xFFFF sendOnePing(mySocket, destAddr, myID) delay = receiveOnePing(mySocket, myID, timeout, destAddr) mySocket.close() return delay def ping(host, timeout=1): dest = gethostbyname(host) print("Pinging " + dest + " using Python:") print() pingTimes = 4 lost = 0 delayList = [] for i in range(pingTimes): res = doOnePing(dest, timeout) if type(res) == str: lost+=1; print(res) continue delay, TTL, packetSize = res delay = int(delay * 1000) delayList.append(delay) print("来自",dest,"的回复: 字节=",packetSize," 时间=",delay,"ms TTL=",TTL) time.sleep(1) print(dest + " 的 Ping 统计信息:") print(" 数据包: 已发送 = ",pingTimes," ,已接收 = ",pingTimes-lost," ,丢失 = ",lost, " ( ",lost/pingTimes*100,"% 丢失)") if len(delayList) > 0: print("往返行程的估计时间(以毫秒为单位):") print("最短 = ",min(delayList),"ms,最长 = ",max(delayList),"ms,平均 = ",sum(delayList)/len(delayList),"ms")
if len(sys.argv) <= 1: print("请输入要ping的主机地址!") exit() ping(sys.argv[1])
|