i keep having a problem in my code coming back as Test Failed: unsupported operand type(s) for : 'int' and 'tuple'.
i am a super beginner who is not very good at coding, so i cannot figure out what the issue is.
here is the full code.
i am making a simple icmp pinger program.
thanks everyone for your help!!! (this is my first question here so please let me know if i need to edit anything)
from socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii
# Should use stdev
ICMP_ECHO_REQUEST = 8
def checksum(string):
csum = 0
countTo = (len(string) // 2) * 2
count = 0
while count < countTo:
thisVal = (string[count 1]) * 256 (string[count])
csum = thisVal
csum &= 0xffffffff
count = 2
if countTo < len(string):
csum = (string[len(string) - 1])
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] == []: # 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, packID, seqNo = struct.unpack("bbHHh", header)
if type == 0 and packID == ID:
bytesInDouble = struct.calcsize("d")
timeSent = struct.unpack("d", recPacket[28:28 bytesInDouble])[0]
ttls = struct.unpack("c", recPacket[8:9])[0]
rtt = timeReceived - timeSent
return (rtt, ttls)
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())
# 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':
# Convert 16-bit integers from host to network byte order
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)) # 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 = getprotobyname("icmp")
# SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw
mySocket = socket(AF_INET, 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):
# 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 = gethostbyname(host)
# print("Pinging " dest " using Python:")
# print("")
# Calculate vars values and return them
count = 0
val = []
# Send ping requests to a server separated by approximately one second
for i in range(0,4):
delay = doOnePing(dest, timeout)
val.append(delay)
# print(delay)
time.sleep(1) # one second
if len(val) > 0:
packet_min = min(val) * 1000
packet_avg = sum(val) / len(val) * 1000
packet_max = max(val) * 1000
stdev_var = list(val) * 1000
vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(stdev(stdev_var), 2))]
else:
vars = ['0', '0.0', '0', '0.0']
return vars
if __name__ == '__main__':
ping("google.co.il")
CodePudding user response:
You have return (rtt, ttls)
in function receiveOnePing
and then you return the same tuple from function doOnePing
. After that, you append this tuple to list and are trying to sum
this list of tuples. This leads to the error you mentioned.
You need val.append(delay[0])
in ping
function (line 122).
You also use undefined function stdev
. Should be statistics.stdev
.
Please note that your script will crash in case of timeout because you return a string in this. Also the code is runnable only by root.
UPD Below is fixed code.
rom socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii
# Should use stdev
ICMP_ECHO_REQUEST = 8
def checksum(string):
csum = 0
countTo = (len(string) // 2) * 2
count = 0
while count < countTo:
thisVal = (string[count 1]) * 256 (string[count])
csum = thisVal
csum &= 0xffffffff
count = 2
if countTo < len(string):
csum = (string[len(string) - 1])
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] == []: # 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, packID, seqNo = struct.unpack("bbHHh", header)
if type == 0 and packID == ID:
bytesInDouble = struct.calcsize("d")
timeSent = struct.unpack("d", recPacket[28:28 bytesInDouble])[0]
ttls = struct.unpack("c", recPacket[8:9])[0]
rtt = timeReceived - timeSent
return (rtt, ttls)
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())
# 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':
# Convert 16-bit integers from host to network byte order
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)) # 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 = getprotobyname("icmp")
# SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw
mySocket = socket(AF_INET, 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):
# 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 = gethostbyname(host)
# print("Pinging " dest " using Python:")
# print("")
# Calculate vars values and return them
count = 0
val = []
# Send ping requests to a server separated by approximately one second
for i in range(0,4):
delay = doOnePing(dest, timeout)
val.append(delay[0])
# print(delay)
time.sleep(1) # one second
print(val)
if len(val) > 0:
packet_min = min(val) * 1000
packet_avg = sum(val) / len(val) * 1000
packet_max = max(val) * 1000
stdev_var = list(val) * 1000
vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(statistics.stdev(stdev_var), 2))]
else:
vars = ['0', '0.0', '0', '0.0']
return vars
if __name__ == '__main__':
ping("google.co.il")
>sudo python3 ping.py
[0.0778355598449707, 0.07866811752319336, 0.07798004150390625, 0.07628297805786133]
CodePudding user response:
The error occurs in this line:
packet_avg = sum(val) / len(val) * 1000
Therefore val
is suspect. Follow the logic back through doOnePing
to receiveOnePing
and you will find that function does not return suitable types.
CodePudding user response:
You have a few issues. What I can see:
you are trying to checksum but in python, using an index returns a string, not a character, so this generates a string, not a number:
thisVal = (string[count 1]) * 256 (string[count])
What you probably want in this case is:
thisVal = ord(string[count 1]) * 256 ord(string[count])
and also on this line:
csum = (string[len(string) - 1])
to
csum = ord(string[len(string) - 1])
Then, you are putting tuples and possibly strings into your val
array.
You need to decide how you want to handle the errors/time out of the ping.
You could just ignore them for now:
for i in range(0,4):
delay = doOnePing(dest, timeout)
if isinstance(delay, tuple):
val.append(delay[0])
time.sleep(1) # one second
That will only add if you received a tuple, and only add the first member of the tuple, which appears to be the delay you want.