You are on page 1of 6

Programming Assignment #2 - UDP Pinger Client

John Fleischli, Levi Remington, Erik Stanton


February 4, 2020

1. Pseudo code from each member.

Erik S.:

import libraries

set server name and port

create client socket

loop 10 times
send message to server
print ping information

if timeout
print timeout message

print complete information/calculations

close socket

John F.:

import libraries

Set server name and port

create client UDP socket


set timeout to 1 second

for loop 10 times


record time request is sent
send message to server

Try to recieve message from server


record time message is received
calculate RTT
print success message with info

except if timeout
print timeout message

close socket
Levi R.:
import all from socket
import time

Set serverName var to IP address of machine running the server


Set serverPort var to 12000 (the port assigned to the socket in the server)

Create timeLog ordered list

Create the client's UDP socket with IPv4 address family


Set the socket's timeout to 1 second

Prompt user for a message to send through the socket


Convert message to byte type.

Print "The message being sent: " + message


Print "Pinging [serverName] with xx bytes of data"

The following for loop will send this message 10 times with a 1-second
timeout, effectively "pinging" the server:

Start timer.
Construct a packet with the appropriate destination address & send it
to the process' socket.

Wait 1 second to receive data from server


End timer.

If the request times out before response is received, print "Request


timed out" and add "0" to timeLog.
If not, put the data into modifiedMessage var and source address into
serverAddress var.
Decode and print modifiedMessage. Calculate then add RTT to timeLog.

If last item in list is not "0" (no timeout occurred),


print "Reply from [serverName]: bytes=XX time=YY seconds"

Close the socket, terminating the process

For all values in timeLog, the number of values = packetsSent.


For values in timeLog that aren't "0", the number of values =
packetsReceived.
The difference between packetsSent and packetsReceived is packetsLost.

Sum of all values that aren't "0" divided by packetsReceived = AvgRTT


MinRTT = min(i for i in timeLog if i > 0)
MaxRTT = max(timeLog)

Print
"Ping statistics for [serverName]:
Packets: Sent = X, Received = Y, Lost = Z (?% Loss),
Approximate round trip times in mili-seconds:
Minimum = XXms, Maximum = YYms, Average = ZZms
"

2. Basis of decision on best approach

Each member's pseudocode featured a similar approach to the problem. Levi's pseudocode was the
most in-depth and provided the framework for our initial design. However, in writing the client program
we diverged from this pseudocode in some ways after reaching a more thorough understanding of the
requirements.

3. Network steps needed (example addresses, sockets)

The only required network steps for setup are noted below:

serverName = 'localhost' # Must match designated serverName and port


serverPort = 12000 # from the server program

clientSocket = socket(AF_INET, SOCK_DGRAM)


clientSocket.settimeout(1)

4. Interesting findings from code review discussion

Setting the time for socket timeout was relatively easy.


Using ‘time.time()’ is far less accurate for measuring short durations than
‘time.perf_counter()’.
However the placement of the start timer was a bit difficult to nail down because we did not want to be
timing unnecessary processes. With our final placement, I believe the only unnecessary process that
may influence the time is the conversion of the time value to string and then encoding that value so that
it can be sent to the server. This was a necessary step since the assignment called for the time of each
ping to be passed as a message ala “This is Ping 1 0.3267296”.

5. Test plan

As there is no user input for running the client program, testing was done first using a user input string,
allowing us to test different length messages.

6. Test results

Although the difference in packet size was too small to show any changes in the time measurements,
the display of bytes did properly change in the program output when different length messages were
entered. In addition, we took one example output and walked through each EstRTT, DevRTT, and
timeout and did the calculations by hand to ensure that the formulas in use by our program were
correct.
Below is a screenshot of of our program in action:
7. Show the final code

# UDPPingerClient.py

from socket import *


import time
from sys import getsizeof

# Initializes array to track RTT


timeLog = []

# Sets the server Name and Port


serverName = 'localhost'
serverPort = 12000

# Creates the client socket with parameters for the address family and the socket type(UDP or TCP)
clientSocket = socket(AF_INET, SOCK_DGRAM)

# Sets the socket timeout to 1 second


clientSocket.settimeout(1)

# Prints ping details to the user


print("Pinging '" + serverName + ":\n")

numPings = 10
previousERTT = 0
previousDRTT = 0
firstERTT = 0

# Loop to ping server 10 times


for x in range(numPings):
# Constructs message based on Ping sequence_number
message = ("This is Ping " + str(x + 1) + " ").encode()

# Stores time when message is being sent and sends the message
t1 = time.perf_counter()
clientSocket.sendto(message + str(t1).encode(), (serverName, serverPort))

try:
# Attempts to recieve a message from the server, if there is an exception, jumps to the exception
handler
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)

# Stores time when message was recieved and adds it to the timeLog
t2 = time.perf_counter()
timeLog.append(t2 - t1)

# Toggle firstERTT on after the previousERTT has been assigned its initial value
if firstERTT == 0:
previousERTT = timeLog[-1]
firstERTT = 1

#print("previousERTT: " + str(previousERTT))


#print("timeLog = " + str(timeLog[-1]))

# Calculates the new ERTT/DRTT and stores in previousERTT/DRTT for the next ping
newERTT = ((1 - 0.125) * previousERTT) + (0.125 * timeLog[-1])
previousERTT = newERTT

newDRTT = ((1 - 0.25) * previousDRTT) + (0.25 * abs(timeLog[-1] - newERTT))


previousDRTT = newDRTT

# Prints the client message & reply message from the server & provides statistics on the ping
print("Message: " + message.decode() + str(t1))
print("Reply from '" + serverName + "' " + str(t2) + " '" + modifiedMessage.decode() + "' | bytes=" +
str(getsizeof(modifiedMessage))
+ " time=" + str(round(timeLog[-1]*1000,2)) + "ms" + " EstRTT=" + str(round((newERTT * 1000),2))
+ "ms"
+ " DevRTT=" + str(round((newDRTT * 1000),2)) + "ms" + " timeout=" + str(round((newERTT +
(4*newDRTT))*1000,2)) + "ms\n")

except:
print("Message: " + message.decode() + str(t1))
print("Request timed out\n")

# Prints detailed summary of all pings for the user


print("\nPing statistics for '" + serverName + "':\n" + "\tPackets: Sent = " + str(numPings) + ", Received = " +
str(len(timeLog))
+ ", Lost = " + str(numPings - len(timeLog)) + ", Loss-Rate = " + str(100 * (numPings - len(timeLog)) /
numPings)
+ "%\n" + "Approximate round trip times in seconds:\n" + "\tMinimum = " + str(round(min(timeLog)*1000,2))
+ "ms, Maximum = " + str(round(max(timeLog)*1000,2)) + "ms, Average = " + str(round((sum(timeLog) /
len(timeLog))*1000,2)) + "ms")

# Closes the socket


clientSocket.close()

You might also like