New Demo - graph pings using canvas. Ping.py pure ping implementation
This commit is contained in:
		
							parent
							
								
									77d68f2384
								
							
						
					
					
						commit
						674d050ca1
					
				
					 2 changed files with 650 additions and 0 deletions
				
			
		
							
								
								
									
										78
									
								
								Demo_Ping_Line_Graph.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Demo_Ping_Line_Graph.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,78 @@ | |||
| import ping | ||||
| from threading import Thread | ||||
| import time | ||||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| # set coordinate system | ||||
| canvas_right = 300 | ||||
| canvas_left = 0 | ||||
| canvas_top = 0 | ||||
| canvas_bottom = 300 | ||||
| # define the coordinates you'll use for your graph | ||||
| x_right = 100 | ||||
| x_left = 0 | ||||
| y_bottom = 0 | ||||
| y_top = 500 | ||||
| 
 | ||||
| # globale used to communicate with thread.. yea yea... it's working fine | ||||
| g_exit = False | ||||
| g_response_time = None | ||||
| 
 | ||||
| def ping_thread(args): | ||||
|     global g_exit, g_response_time | ||||
| 
 | ||||
|     while not g_exit: | ||||
|         g_response_time = ping.quiet_ping('google.com', timeout=1000) | ||||
| 
 | ||||
| 
 | ||||
| def convert_xy_to_canvas_xy(x_in,y_in): | ||||
|     scale_x = (canvas_right - canvas_left) / (x_right - x_left) | ||||
|     scale_y = (canvas_top - canvas_bottom) / (y_top - y_bottom) | ||||
|     new_x = canvas_left + scale_x * (x_in - x_left) | ||||
|     new_y = canvas_bottom + scale_y * (y_in - y_bottom) | ||||
|     return new_x, new_y | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # start ping measurement thread | ||||
| thread = Thread(target=ping_thread, args=(None,)) | ||||
| thread.start() | ||||
| 
 | ||||
| layout = [  [sg.T('Ping times to Google.com', font='Any 18')], | ||||
|            [sg.Canvas(size=(canvas_right, canvas_bottom), background_color='white', key='canvas')], | ||||
|            [sg.Quit()] | ||||
|            ] | ||||
| 
 | ||||
| form = sg.FlexForm('Canvas test', grab_anywhere=True) | ||||
| form.Layout(layout) | ||||
| form.Finalize() | ||||
| 
 | ||||
| canvas = form.FindElement('canvas').TKCanvas | ||||
| 
 | ||||
| prev_response_time = None | ||||
| i=0 | ||||
| prev_x, prev_y  = canvas_left, canvas_bottom | ||||
| while True: | ||||
|     time.sleep(.2) | ||||
| 
 | ||||
|     button, values = form.ReadNonBlocking() | ||||
|     if button == 'Quit' or values is None: | ||||
|         break | ||||
| 
 | ||||
|     if g_response_time is None or prev_response_time == g_response_time: | ||||
|         continue | ||||
|     new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0]) | ||||
|     prev_response_time = g_response_time | ||||
|     canvas.create_line(prev_x, prev_y, new_x, new_y, width=1, fill='black') | ||||
|     prev_x, prev_y = new_x, new_y | ||||
|     if i >= x_right: | ||||
|         i = 0 | ||||
|         prev_x = prev_y = last_x = last_y = 0 | ||||
|     else: i += 1 | ||||
| 
 | ||||
| # tell thread we're done. wait for thread to exit | ||||
| g_exit = True | ||||
| thread.join() | ||||
| 
 | ||||
| 
 | ||||
| exit(69) | ||||
							
								
								
									
										572
									
								
								ping.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										572
									
								
								ping.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,572 @@ | |||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| """ | ||||
|     A pure python ping implementation using raw sockets. | ||||
| 
 | ||||
|     (This is Python 3 port of https://github.com/jedie/python-ping) | ||||
|     (Tested and working with python 2.7, should work with 2.6+) | ||||
| 
 | ||||
|     Note that ICMP messages can only be sent from processes running as root | ||||
|     (in Windows, you must run this script as 'Administrator'). | ||||
| 
 | ||||
|     Derived from ping.c distributed in Linux's netkit. That code is | ||||
|     copyright (c) 1989 by The Regents of the University of California. | ||||
|     That code is in turn derived from code written by Mike Muuss of the | ||||
|     US Army Ballistic Research Laboratory in December, 1983 and | ||||
|     placed in the public domain. They have my thanks. | ||||
| 
 | ||||
|     Bugs are naturally mine. I'd be glad to hear about them. There are | ||||
|     certainly word - size dependencies here. | ||||
| 
 | ||||
|     Copyright (c) Matthew Dixon Cowles, <http://www.visi.com/~mdc/>. | ||||
|     Distributable under the terms of the GNU General Public License | ||||
|     version 2. Provided with no warranties of any sort. | ||||
| 
 | ||||
|     Original Version from Matthew Dixon Cowles: | ||||
|       -> ftp://ftp.visi.com/users/mdc/ping.py | ||||
| 
 | ||||
|     Rewrite by Jens Diemer: | ||||
|       -> http://www.python-forum.de/post-69122.html#69122 | ||||
| 
 | ||||
|     Rewrite by George Notaras: | ||||
|       -> http://www.g-loaded.eu/2009/10/30/python-ping/ | ||||
| 
 | ||||
|     Enhancements by Martin Falatic: | ||||
|       -> http://www.falatic.com/index.php/39/pinging-with-python | ||||
| 
 | ||||
|     Enhancements and fixes by Georgi Kolev: | ||||
|       -> http://github.com/jedie/python-ping/ | ||||
| 
 | ||||
|     Bug fix by Andrejs Rozitis: | ||||
|       -> http://github.com/rozitis/python-ping/ | ||||
| 
 | ||||
|     Revision history | ||||
|     ~~~~~~~~~~~~~~~~ | ||||
|     May 1, 2014 | ||||
|     ----------- | ||||
|     Little modifications by Mohammad Emami <emamirazavi@gmail.com> | ||||
|     - Added Python 3 support. For now this project will just support  | ||||
|       python 3.x | ||||
|     - Tested with python 3.3 | ||||
|     - version was upped to 0.6  | ||||
| 
 | ||||
|     March 19, 2013 | ||||
|     -------------- | ||||
|     * Fixing bug to prevent divide by 0 during run-time. | ||||
| 
 | ||||
|     January 26, 2012 | ||||
|     ---------------- | ||||
|     * Fixing BUG #4 - competability with python 2.x [tested with 2.7] | ||||
|       - Packet data building is different for 2.x and 3.x. | ||||
|         'cose of the string/bytes difference. | ||||
|     * Fixing BUG #10 - the multiple resolv issue. | ||||
|       - When pinging domain names insted of hosts (for exmaple google.com) | ||||
|         you can get different IP every time you try to resolv it, we should | ||||
|         resolv the host only once and stick to that IP. | ||||
|     * Fixing BUGs #3 #10 - Doing hostname resolv only once. | ||||
|     * Fixing BUG #14 - Removing all 'global' stuff. | ||||
|         - You should not use globul! Its bad for you...and its not thread safe! | ||||
|     * Fix - forcing the use of different times on linux/windows for | ||||
|             more accurate mesurments. (time.time - linux/ time.clock - windows) | ||||
|     * Adding quiet_ping function - This way we'll be able to use this script | ||||
|         as external lib. | ||||
|     * Changing default timeout to 3s. (1second is not enought) | ||||
|     * Switching data syze to packet size. It's easyer for the user to ignore the | ||||
|         fact that the packet headr is 8b and the datasize 64 will make packet with | ||||
|         size 72. | ||||
| 
 | ||||
|     October 12, 2011 | ||||
|     -------------- | ||||
|     Merged updates from the main project | ||||
|       -> https://github.com/jedie/python-ping | ||||
| 
 | ||||
|     September 12, 2011 | ||||
|     -------------- | ||||
|     Bugfixes + cleanup by Jens Diemer | ||||
|     Tested with Ubuntu + Windows 7 | ||||
| 
 | ||||
|     September 6, 2011 | ||||
|     -------------- | ||||
|     Cleanup by Martin Falatic. Restored lost comments and docs. Improved | ||||
|     functionality: constant time between pings, internal times consistently | ||||
|     use milliseconds. Clarified annotations (e.g., in the checksum routine). | ||||
|     Using unsigned data in IP & ICMP header pack/unpack unless otherwise | ||||
|     necessary. Signal handling. Ping-style output formatting and stats. | ||||
| 
 | ||||
|     August 3, 2011 | ||||
|     -------------- | ||||
|     Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to | ||||
|     deal with bytes vs. string changes (no more ord() in checksum() because | ||||
|     >source_string< is actually bytes, added .encode() to data in | ||||
|     send_one_ping()).  That's about it. | ||||
| 
 | ||||
|     March 11, 2010 | ||||
|     -------------- | ||||
|     changes by Samuel Stauffer: | ||||
|     - replaced time.clock with default_timer which is set to | ||||
|       time.clock on windows and time.time on other systems. | ||||
| 
 | ||||
|     November 8, 2009 | ||||
|     ---------------- | ||||
|     Improved compatibility with GNU/Linux systems. | ||||
| 
 | ||||
|     Fixes by: | ||||
|      * George Notaras -- http://www.g-loaded.eu | ||||
|     Reported by: | ||||
|      * Chris Hallman -- http://cdhallman.blogspot.com | ||||
| 
 | ||||
|     Changes in this release: | ||||
|      - Re-use time.time() instead of time.clock(). The 2007 implementation | ||||
|        worked only under Microsoft Windows. Failed on GNU/Linux. | ||||
|        time.clock() behaves differently under the two OSes[1]. | ||||
| 
 | ||||
|     [1] http://docs.python.org/library/time.html#time.clock | ||||
| 
 | ||||
|     May 30, 2007 | ||||
|     ------------ | ||||
|     little rewrite by Jens Diemer: | ||||
|      -  change socket asterisk import to a normal import | ||||
|      -  replace time.time() with time.clock() | ||||
|      -  delete "return None" (or change to "return" only) | ||||
|      -  in checksum() rename "str" to "source_string" | ||||
| 
 | ||||
|     December 4, 2000 | ||||
|     ---------------- | ||||
|     Changed the struct.pack() calls to pack the checksum and ID as | ||||
|     unsigned. My thanks to Jerome Poincheval for the fix. | ||||
| 
 | ||||
|     November 22, 1997 | ||||
|     ----------------- | ||||
|     Initial hack. Doesn't do much, but rather than try to guess | ||||
|     what features I (or others) will want in the future, I've only | ||||
|     put in what I need now. | ||||
| 
 | ||||
|     December 16, 1997 | ||||
|     ----------------- | ||||
|     For some reason, the checksum bytes are in the wrong order when | ||||
|     this is run under Solaris 2.X for SPARC but it works right under | ||||
|     Linux x86. Since I don't know just what's wrong, I'll swap the | ||||
|     bytes always and then do an htons(). | ||||
| 
 | ||||
|     =========================================================================== | ||||
|     IP header info from RFC791 | ||||
|       -> http://tools.ietf.org/html/rfc791) | ||||
| 
 | ||||
|     0                   1                   2                   3 | ||||
|     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |Version|  IHL  |Type of Service|          Total Length         | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |         Identification        |Flags|      Fragment Offset    | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |  Time to Live |    Protocol   |         Header Checksum       | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |                       Source Address                          | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |                    Destination Address                        | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|     |                    Options                    |    Padding    | | ||||
|     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| 
 | ||||
|     =========================================================================== | ||||
|     ICMP Echo / Echo Reply Message header info from RFC792 | ||||
|       -> http://tools.ietf.org/html/rfc792 | ||||
| 
 | ||||
|         0                   1                   2                   3 | ||||
|         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||||
|         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|         |     Type      |     Code      |          Checksum             | | ||||
|         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|         |           Identifier          |        Sequence Number        | | ||||
|         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
|         |     Data ... | ||||
|         +-+-+-+-+- | ||||
| 
 | ||||
|     =========================================================================== | ||||
|     ICMP parameter info: | ||||
|       -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml | ||||
| 
 | ||||
|     =========================================================================== | ||||
|     An example of ping's typical output: | ||||
| 
 | ||||
|     PING heise.de (193.99.144.80): 56 data bytes | ||||
|     64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms | ||||
|     64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms | ||||
|     64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms | ||||
|     64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms | ||||
|     64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms | ||||
| 
 | ||||
|     ----heise.de PING Statistics---- | ||||
|     5 packets transmitted, 5 packets received, 0.0% packet loss | ||||
|     round-trip (ms)  min/avg/max/med = 126/127/127/127 | ||||
| 
 | ||||
|     =========================================================================== | ||||
| """ | ||||
| 
 | ||||
| #=============================================================================# | ||||
| import argparse | ||||
| import os, sys, socket, struct, select, time, signal | ||||
| 
 | ||||
| __description__ = 'A pure python ICMP ping implementation using raw sockets.' | ||||
| 
 | ||||
| if sys.platform == "win32": | ||||
|     # On Windows, the best timer is time.clock() | ||||
|     default_timer = time.clock | ||||
| else: | ||||
|     # On most other platforms the best timer is time.time() | ||||
|     default_timer = time.time | ||||
| 
 | ||||
| NUM_PACKETS = 3 | ||||
| PACKET_SIZE = 64 | ||||
| WAIT_TIMEOUT = 3.0 | ||||
| 
 | ||||
| #=============================================================================# | ||||
| # ICMP parameters | ||||
| 
 | ||||
| ICMP_ECHOREPLY  =    0 # Echo reply (per RFC792) | ||||
| ICMP_ECHO       =    8 # Echo request (per RFC792) | ||||
| ICMP_MAX_RECV   = 2048 # Max size of incoming buffer | ||||
| 
 | ||||
| MAX_SLEEP = 1000 | ||||
| 
 | ||||
| class MyStats: | ||||
|     thisIP   = "0.0.0.0" | ||||
|     pktsSent = 0 | ||||
|     pktsRcvd = 0 | ||||
|     minTime  = 999999999 | ||||
|     maxTime  = 0 | ||||
|     totTime  = 0 | ||||
|     avrgTime = 0 | ||||
|     fracLoss = 1.0 | ||||
| 
 | ||||
| myStats = MyStats # NOT Used globally anymore. | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def checksum(source_string): | ||||
|     """ | ||||
|     A port of the functionality of in_cksum() from ping.c | ||||
|     Ideally this would act on the string as a series of 16-bit ints (host | ||||
|     packed), but this works. | ||||
|     Network data is big-endian, hosts are typically little-endian | ||||
|     """ | ||||
|     countTo = (int(len(source_string)/2))*2 | ||||
|     sum = 0 | ||||
|     count = 0 | ||||
| 
 | ||||
|     # Handle bytes in pairs (decoding as short ints) | ||||
|     loByte = 0 | ||||
|     hiByte = 0 | ||||
|     while count < countTo: | ||||
|         if (sys.byteorder == "little"): | ||||
|             loByte = source_string[count] | ||||
|             hiByte = source_string[count + 1] | ||||
|         else: | ||||
|             loByte = source_string[count + 1] | ||||
|             hiByte = source_string[count] | ||||
|         try:     # For Python3 | ||||
|             sum = sum + (hiByte * 256 + loByte) | ||||
|         except:  # For Python2 | ||||
|             sum = sum + (ord(hiByte) * 256 + ord(loByte)) | ||||
|         count += 2 | ||||
| 
 | ||||
|     # Handle last byte if applicable (odd-number of bytes) | ||||
|     # Endianness should be irrelevant in this case | ||||
|     if countTo < len(source_string): # Check for odd length | ||||
|         loByte = source_string[len(source_string)-1] | ||||
|         try:      # For Python3 | ||||
|             sum += loByte | ||||
|         except:   # For Python2 | ||||
|             sum += ord(loByte) | ||||
| 
 | ||||
|     sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which | ||||
|                       # uses signed ints, but overflow is unlikely in ping) | ||||
| 
 | ||||
|     sum = (sum >> 16) + (sum & 0xffff)    # Add high 16 bits to low 16 bits | ||||
|     sum += (sum >> 16)                    # Add carry from above (if any) | ||||
|     answer = ~sum & 0xffff                # Invert and truncate to 16 bits | ||||
|     answer = socket.htons(answer) | ||||
| 
 | ||||
|     return answer | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet = False): | ||||
|     """ | ||||
|     Returns either the delay (in ms) or None on timeout. | ||||
|     """ | ||||
|     delay = None | ||||
| 
 | ||||
|     try: # One could use UDP here, but it's obscure | ||||
|         mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp")) | ||||
|     except socket.error as e: | ||||
|         print("failed. (socket error: '%s')" % e.args[1]) | ||||
|         raise # raise the original error | ||||
| 
 | ||||
|     my_ID = os.getpid() & 0xFFFF | ||||
| 
 | ||||
|     sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size) | ||||
|     if sentTime == None: | ||||
|         mySocket.close() | ||||
|         return delay | ||||
| 
 | ||||
|     myStats.pktsSent += 1 | ||||
| 
 | ||||
|     recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout) | ||||
| 
 | ||||
|     mySocket.close() | ||||
| 
 | ||||
|     if recvTime: | ||||
|         delay = (recvTime-sentTime)*1000 | ||||
|         if not quiet: | ||||
|             print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % ( | ||||
|                 dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay) | ||||
|             ) | ||||
|         myStats.pktsRcvd += 1 | ||||
|         myStats.totTime += delay | ||||
|         if myStats.minTime > delay: | ||||
|             myStats.minTime = delay | ||||
|         if myStats.maxTime < delay: | ||||
|             myStats.maxTime = delay | ||||
|     else: | ||||
|         delay = None | ||||
|         print("Request timed out.") | ||||
| 
 | ||||
|     return delay | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size): | ||||
|     """ | ||||
|     Send one ping to the given >destIP<. | ||||
|     """ | ||||
|     #destIP  =  socket.gethostbyname(destIP) | ||||
| 
 | ||||
|     # Header is type (8), code (8), checksum (16), id (16), sequence (16) | ||||
|     # (packet_size - 8) - Remove header size from packet size | ||||
|     myChecksum = 0 | ||||
| 
 | ||||
|     # Make a dummy heder with a 0 checksum. | ||||
|     header = struct.pack( | ||||
|         "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber | ||||
|     ) | ||||
| 
 | ||||
|     padBytes = [] | ||||
|     startVal = 0x42 | ||||
|     # 'cose of the string/byte changes in python 2/3 we have | ||||
|     # to build the data differnely for different version | ||||
|     # or it will make packets with unexpected size. | ||||
|     if sys.version[:1] == '2': | ||||
|         bytes = struct.calcsize("d") | ||||
|         data = ((packet_size - 8) - bytes) * "Q" | ||||
|         data = struct.pack("d", default_timer()) + data | ||||
|     else: | ||||
|         for i in range(startVal, startVal + (packet_size-8)): | ||||
|             padBytes += [(i & 0xff)]  # Keep chars in the 0-255 range | ||||
|         #data = bytes(padBytes) | ||||
|         data = bytearray(padBytes) | ||||
| 
 | ||||
| 
 | ||||
|     # Calculate the checksum on the data and the dummy header. | ||||
|     myChecksum = checksum(header + data) # Checksum is in network order | ||||
| 
 | ||||
|     # Now that we have the right checksum, we put that in. It's just easier | ||||
|     # to make up a new header than to stuff it into the dummy. | ||||
|     header = struct.pack( | ||||
|         "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber | ||||
|     ) | ||||
| 
 | ||||
|     packet = header + data | ||||
| 
 | ||||
|     sendTime = default_timer() | ||||
| 
 | ||||
|     try: | ||||
|         mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP | ||||
|     except socket.error as e: | ||||
|         print("General failure (%s)" % (e.args[1])) | ||||
|         return | ||||
| 
 | ||||
|     return sendTime | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def receive_one_ping(mySocket, myID, timeout): | ||||
|     """ | ||||
|     Receive the ping from the socket. Timeout = in ms | ||||
|     """ | ||||
|     timeLeft = timeout/1000 | ||||
| 
 | ||||
|     while True: # Loop while waiting for packet or timeout | ||||
|         startedSelect = default_timer() | ||||
|         whatReady = select.select([mySocket], [], [], timeLeft) | ||||
|         howLongInSelect = (default_timer() - startedSelect) | ||||
|         if whatReady[0] == []: # Timeout | ||||
|             return None, 0, 0, 0, 0 | ||||
| 
 | ||||
|         timeReceived = default_timer() | ||||
| 
 | ||||
|         recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV) | ||||
| 
 | ||||
|         ipHeader = recPacket[:20] | ||||
|         iphVersion, iphTypeOfSvc, iphLength, \ | ||||
|         iphID, iphFlags, iphTTL, iphProtocol, \ | ||||
|         iphChecksum, iphSrcIP, iphDestIP = struct.unpack( | ||||
|             "!BBHHHBBHII", ipHeader | ||||
|         ) | ||||
| 
 | ||||
|         icmpHeader = recPacket[20:28] | ||||
|         icmpType, icmpCode, icmpChecksum, \ | ||||
|         icmpPacketID, icmpSeqNumber = struct.unpack( | ||||
|             "!BBHHH", icmpHeader | ||||
|         ) | ||||
| 
 | ||||
|         if icmpPacketID == myID: # Our packet | ||||
|             dataSize = len(recPacket) - 28 | ||||
|             #print (len(recPacket.encode())) | ||||
|             return timeReceived, (dataSize+8), iphSrcIP, icmpSeqNumber, iphTTL | ||||
| 
 | ||||
|         timeLeft = timeLeft - howLongInSelect | ||||
|         if timeLeft <= 0: | ||||
|             return None, 0, 0, 0, 0 | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def dump_stats(myStats): | ||||
|     """ | ||||
|     Show stats when pings are done | ||||
|     """ | ||||
|     print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP)) | ||||
| 
 | ||||
|     if myStats.pktsSent > 0: | ||||
|         myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent | ||||
| 
 | ||||
|     print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % ( | ||||
|         myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss | ||||
|     )) | ||||
| 
 | ||||
|     if myStats.pktsRcvd > 0: | ||||
|         print("round-trip (ms)  min/avg/max = %d/%0.1f/%d" % ( | ||||
|             myStats.minTime, myStats.totTime/myStats.pktsRcvd, myStats.maxTime | ||||
|         )) | ||||
| 
 | ||||
|     print("") | ||||
|     return | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def signal_handler(signum, frame): | ||||
|     """ | ||||
|     Handle exit via signals | ||||
|     """ | ||||
|     dump_stats() | ||||
|     print("\n(Terminated with signal %d)\n" % (signum)) | ||||
|     sys.exit(0) | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, | ||||
|                  packet_size=PACKET_SIZE, path_finder=False): | ||||
|     """ | ||||
|     Send >count< ping to >destIP< with the given >timeout< and display | ||||
|     the result. | ||||
|     """ | ||||
|     signal.signal(signal.SIGINT, signal_handler)   # Handle Ctrl-C | ||||
|     if hasattr(signal, "SIGBREAK"): | ||||
|         # Handle Ctrl-Break e.g. under Windows | ||||
|         signal.signal(signal.SIGBREAK, signal_handler) | ||||
| 
 | ||||
|     myStats = MyStats() # Reset the stats | ||||
| 
 | ||||
|     mySeqNumber = 0 # Starting value | ||||
| 
 | ||||
|     try: | ||||
|         destIP = socket.gethostbyname(hostname) | ||||
|         print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size)) | ||||
|     except socket.gaierror as e: | ||||
|         print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1])) | ||||
|         print() | ||||
|         return | ||||
| 
 | ||||
|     myStats.thisIP = destIP | ||||
| 
 | ||||
|     for i in range(count): | ||||
|         delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size) | ||||
| 
 | ||||
|         if delay == None: | ||||
|             delay = 0 | ||||
| 
 | ||||
|         mySeqNumber += 1 | ||||
| 
 | ||||
|         # Pause for the remainder of the MAX_SLEEP period (if applicable) | ||||
|         if (MAX_SLEEP > delay): | ||||
|             time.sleep((MAX_SLEEP - delay)/1000) | ||||
| 
 | ||||
|     dump_stats(myStats) | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS, | ||||
|                packet_size=PACKET_SIZE, path_finder=False): | ||||
|     """ | ||||
|     Same as verbose_ping, but the results are returned as tuple | ||||
|     """ | ||||
|     myStats = MyStats() # Reset the stats | ||||
|     mySeqNumber = 0 # Starting value | ||||
| 
 | ||||
|     try: | ||||
|         destIP = socket.gethostbyname(hostname) | ||||
|     except socket.gaierror as e: | ||||
|         return False | ||||
| 
 | ||||
|     myStats.thisIP = destIP | ||||
| 
 | ||||
|     # This will send packet that we dont care about 0.5 seconds before it starts | ||||
|     # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes | ||||
|     # loose the first packet. (while the switches find the way... :/ ) | ||||
|     if path_finder: | ||||
|         fakeStats = MyStats() | ||||
|         do_one(fakeStats, destIP, hostname, timeout, | ||||
|                         mySeqNumber, packet_size, quiet=True) | ||||
|         time.sleep(0.5) | ||||
| 
 | ||||
|     for i in range(count): | ||||
|         delay = do_one(myStats, destIP, hostname, timeout, | ||||
|                         mySeqNumber, packet_size, quiet=True) | ||||
| 
 | ||||
|         if delay == None: | ||||
|             delay = 0 | ||||
| 
 | ||||
|         mySeqNumber += 1 | ||||
| 
 | ||||
|         # Pause for the remainder of the MAX_SLEEP period (if applicable) | ||||
|         if (MAX_SLEEP > delay): | ||||
|             time.sleep((MAX_SLEEP - delay)/1000) | ||||
| 
 | ||||
|     if myStats.pktsSent > 0: | ||||
|         myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent | ||||
|     if myStats.pktsRcvd > 0: | ||||
|         myStats.avrgTime = myStats.totTime / myStats.pktsRcvd | ||||
| 
 | ||||
|     # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost) | ||||
|     return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss | ||||
| 
 | ||||
| #=============================================================================# | ||||
| def main(): | ||||
|      | ||||
|     parser = argparse.ArgumentParser(description=__description__) | ||||
|     parser.add_argument('-q', '--quiet', action='store_true', | ||||
|                         help='quiet output') | ||||
|     parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS, | ||||
|                         help=('number of packets to be sent ' | ||||
|                               '(default: %(default)s)')) | ||||
|     parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT, | ||||
|                         help=('time to wait for a response in seoncds ' | ||||
|                               '(default: %(default)s)')) | ||||
|     parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE, | ||||
|                         help=('number of data bytes to be sent ' | ||||
|                               '(default: %(default)s)')) | ||||
|     parser. add_argument('destination') | ||||
|     # args = parser.parse_args() | ||||
| 
 | ||||
|     ping = verbose_ping | ||||
|     # if args.quiet: | ||||
|     # ping = quiet_ping | ||||
|     ping('Google.com', timeout=1000) | ||||
|     # ping(args.destination, timeout=args.timeout*1000, count=args.count, | ||||
|     #      packet_size=args.packet_size) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue