#!/usr/bin/env python#Coding=utf-8ImportOSImportArgparseImportSocketImportstructImportSelectImportTime icmp_echo_request= 8#Platform SpecificDefault_timeout = 2Default_count= 4classPinger (object):"""Pings to a host-the Pythonic""" def __init__(Self, target_host, Count=default_count, timeout=default_timeout): Self.target_host=target_host Self.count=Count Self.timeout=Timeoutdefdo_checksum (Self, source_string):"""Verify the packet integritity"""sum=0 Max_count= (len (source_string)/2) * *Count=0 whileCount < max_count:#split data every two bits (16bit) for a set ofval = ord (Source_string[count + 1]) *256 +Ord (Source_string[count]) sum= Sum +val Sum= Sum & 0xFFFFFFFFCount= Count + 2ifMax_count<len (source_string):#If the data length is cardinality, the last one is added separatelysum = sum + ord (Source_string[len (source_string)-1]) sum= Sum & 0xFFFFFFFFsum= (sum >> +) + (sum & 0xffff)#Add the high 16 bits to the lower 16 bits until the high 16 bits are 0sum = sum + (sum >> 16) Answer= ~sum answer= Answer & 0xFFFFAnswer= Answer >> 8 | (Answer << 8 & 0xff00) returnAnswer#returns a decimal integer defreceive_ping (self, sock, ID, timeout):"""Receive Ping from the socket. """time_remaining=Timeout whileTrue:start_time=time.time () readable=Select.select ([sock], [], [], time_remaining) time_spent= (Time.time ()-start_time)ifReadable[0] = = []:#Timeout returntime_received=time.time () recv_packet, addr= Sock.recvfrom (1024) Icmp_header= recv_packet[20:28] Type, code, checksum, packet_id, sequence=Struct.unpack ("bbhhh", Icmp_header)ifpacket_id = =id:bytes_in_double= Struct.calcsize ("D") Time_sent= Struct.unpack ("D", recv_packet[28:28 +Bytes_in_double]) [0]returnTime_received-time_sent time_remaining= Time_remaining-time_spentifTime_remaining <=0:return defsend_ping (self, Sock, ID):#Send Ping to the target hostTARGET_ADDR =socket.gethostbyname (self.target_host) my_checksum=0#Create a dummy heder with a 0 checksum.Header = Struct.pack ("bbhhh", Icmp_echo_request, 0, My_checksum, ID, 1) bytes_in_double= Struct.calcsize ("D") Data= (192-bytes_in_double) *"Q"Data= Struct.pack ("D", Time.time ()) +Data#Get the checksum on the data and the dummy header.My_checksum = Self.do_checksum (header +data) Header=Struct.pack ("bbhhh", Icmp_echo_request, 0, Socket.htons (my_checksum), ID, 1) Packet= Header +Data sock.sendto (packet, (TARGET_ADDR,1)) defping_once (self):"""Returns The delay (in seconds) or none on timeout. """ICMP= Socket.getprotobyname ("ICMP") Try: Sock=Socket.socket (socket.af_inet, socket. Sock_raw, ICMP)exceptSocket.error, (errno, msg):iferrno = = 1: #Not Superuser, so operation not permittedmsg + ="ICMP messages can only is sent from root user processes" Raisesocket.error (msg)exceptException, E:Print "Exception:%s"%(e) my_id= Os.getpid () & 0xFFFFself.send_ping (sock, my_id) delay=self.receive_ping (sock, my_id, Self.timeout) sock.close ()returnDelaydefPing (self):"""Run the ping process""" forIinchxrange (self.count):Print "Ping to%s ..."%Self.target_host,Try: Delay=self.ping_once ()exceptSocket.gaierror, E:Print "Ping failed. (Socket error: '%s ')"% e[1] Break ifDelay = =None:Print "Ping failed. (timeout within%ssec.)"%Self.timeoutElse: Delay= Delay * 1000Print "Get Ping in%0.4fms"%Delayif __name__=='__main__': Parser= Argparse. Argumentparser (description='Python Ping') parser.add_argument ('--target-host', action="Store", dest="Target_host", required=True) Given_args=Parser.parse_args () target_host=Given_args.target_host Pinger= Pinger (Target_host=target_host, count=5, timeout=5) pinger.ping ()
Implementing ping with Python