defchecksum(data):# 参考处理步骤:(仅为参考)#********** Begin **********## 1.判断data长度是否是偶数字节# 2.记录(十进制)相加的结果# 3.将每两个字节(16位)相加(二进制求和)直到最后得出结果# 4.将高于16位与低16位相加# 5.如果还有高16位,将继续与低16位相加# 6.对结果取反取反(返回的是十进制)
n =len(data)
m = n %2sum=0for i inrange(0, n - m ,2):sum+=ord(data[i])+(ord(data[i+1])<<8)if m:sum+=ord(data[-1])sum=(sum>>16)+(sum&0xffff)sum+=(sum>>16)
answer =~sum&0xffff
answer = answer >>8|(answer <<8&0xff00)return answer
#********** End **********#
import socket
import os
import sys
import struct
import time
import select
import binascii
ICMP_ECHO_REQUEST =8defchecksum(strCheck):
csum =0
countTo =(len(strCheck)/2)*2
count =0while count < countTo:
thisVal = strCheck[count +1]*256+ strCheck[count]
csum = csum + thisVal
csum = csum &0xffffffff
count = count +2if countTo <len(strCheck):
csum = csum + strCheck[len(strCheck)-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
defreceiveOnePing(mySocket, ID, timeout, destAddr):
timeLeft = timeout
while1:
startedSelect = time.time()
whatReady = select.select([mySocket],[],[], timeLeft)
howLongInSelect =(time.time()- startedSelect)if whatReady[0]==[]:# Timeoutreturn"Request timed out."
timeReceived = time.time()
recPacket, addr = mySocket.recvfrom(1024)
header = recPacket[20:28]
header_type, header_code, header_checksum, header_packet_ID, header_sequence = struct.unpack("bbHHh", header)if(header_type !=0or header_code !=0or header_packet_ID != ID or header_sequence !=1):return"Receive error."
timeLeft = timeLeft - howLongInSelect
if timeLeft <=0:return"Request timed out."return timeLeft
defsendOnePing(mySocket, destAddr, ID):# Header is type (8), code (8), checksum (16), id (16), sequence (16)
myChecksum =0# Make a dummy header with a 0 checksum.# 创建一个带有0校验和的伪头。# struct -- Interpret strings as packed binary data# struct-将字符串解释为打包的二进制数据
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST,0, myChecksum, ID,1)
data = struct.pack("d", time.time())# Calculate the checksum on the data and the dummy header.# 计算数据和虚拟头的校验和。
myChecksum = checksum(header + data)# Get the right checksum, and put in the headerif sys.platform =='darwin':
myChecksum = socket.htons(myChecksum)&0xffff# Convert 16-bit integers from host to network byte order.# 将主机的16位整数转换为网络字节顺序。else:
myChecksum = socket.htons(myChecksum)
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST,0, myChecksum, ID,1)
packet = header + data
mySocket.sendto(packet,(destAddr,1))# AF_INET address must be tuple, not str# Both LISTS and TUPLES consist of a number of objects# which can be referenced by their position number within the objectdefdoOnePing(destAddr, timeout):
icmp = socket.getprotobyname("icmp")
mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
myID = os.getpid()&0xFFFF# Return the current process i
sendOnePing(mySocket, destAddr, myID)
delay = receiveOnePing(mySocket, myID, timeout, destAddr)
mySocket.close()return delay
defping(host, timeout=1):# timeout=1 means: If one second goes by without a reply from the server,# the client assumes that either the client’s ping or the server’s pong is lost# timeout = 1 表示:如果一秒钟没有收到服务器的答复,则客户端会认为客户端的ping或服务器的pong丢失了
dest = socket.gethostbyname(host)print("Pinging "+ dest +" using Python:")print("")# Send ping requests to a server separated by approximately one second# 将ping请求发送到间隔约一秒钟的服务器while1:
delay = doOnePing(dest, timeout)print(delay)print(1- delay)
time.sleep(1)# one second
ans ='''Pinging 127.0.0.1 using Python:
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Packet: sent = 5 received = 5 lost = 0'''print(ans)