-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsample_pinger.py
More file actions
131 lines (103 loc) · 4.08 KB
/
Copy pathsample_pinger.py
File metadata and controls
131 lines (103 loc) · 4.08 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
import datetime
import os
import sys
import struct
import time
import select
import socket
import binascii
ICMP_ECHO_REQUEST = 8
rtt_min = float('+inf')
rtt_max = float('-inf')
rtt_sum = 0
rtt_cnt = 0
def checksum(string):
csum = 0
countTo = (len(string) / 2) * 2
count = 0
while count < countTo:
thisVal = string[count + 1] * 256 + string[count]
csum = csum + thisVal
csum = csum & 0xffffffff
count = count + 2
if countTo < len(string):
csum = csum + ord(string[len(str) - 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):
global rtt_min, rtt_max, rtt_sum, rtt_cnt
timeLeft = timeout
while 1:
startedSelect = time.time()
whatReady = select.select([mySocket], [], [], timeLeft)
howLongInSelect = (time.time() - startedSelect)
if whatReady[0] == []: # Timeout
return "Request timed out."
timeReceived = time.time()
recPacket, addr = mySocket.recvfrom(1024)
# Fetch the ICMP header from the IP packet
header = recPacket[20:28]
type, code, checksum, id, sequence = struct.unpack("bbHHh", header)
if type == 0 and id == ID:
rtt = (timeReceived - struct.unpack("d", recPacket[28:28 + struct.calcsize("d")])[0]) * 1000 # Calculate the RTT in milliseconds
rtt_min = min(rtt, rtt_min)
rtt_max = max(rtt, rtt_max)
rtt_sum += rtt
rtt_cnt += 1
return f"{len(recPacket)} bytes from {destAddr}; time = {rtt:.2f} ms"
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return "Request timed out."
def sendOnePing(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.
# struct -- Interpret strings as packed binary data
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
data = struct.pack("d", time.time()) # 8 bytes
# Calculate the checksum on the data and the dummy header.
myChecksum = checksum(header + data)
# Get the right checksum, and put in the header
if sys.platform == 'darwin':
myChecksum = socket.htons(myChecksum) & 0xffff
# Convert 16-bit integers from host to network byte order.
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 object
def doOnePing(destAddr, timeout):
icmp = socket.getprotobyname("icmp")
# SOCK_RAW is a powerful socket type. For more details see: http://sock-raw.org/papers/sock_raw
# Create Socket here
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
def ping(host, timeout=1):
global rtt_min, rtt_max, rtt_sum, rtt_cnt
cnt = 0
# 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
dest = socket.gethostbyname(host)
print("Pinging " + dest + " using Python:")
# Send ping requests to a server separated by approximately one second
try:
while True:
cnt += 1
print(doOnePing(dest, timeout))
time.sleep(1)
except KeyboardInterrupt:
print(f"--- {dest} ping statistics ---")
print(f"round-trip min/avg/max {rtt_min:.3f}/{rtt_sum/rtt_cnt:.3f}/{rtt_max:.3f}")
if __name__ == '__main__':
ping(sys.argv[1])