Montana Tech of The University of Montana
Computer Science & Software Engineering

CSCI 466
Networks
Fall 2013



PROGRAM #2

The goal of this assignment is to learn the basic of UDP socket programming in Python. You will also be running an experiment to measure real-world latencies, jitter, and packet loss on the Internet.


Ping server
In this assignment, we are giving you a complete working version of a UDP ping server program. The server waits for a UDP packet to arrive from some client on a certain socket port. It then echoes back the payload of the packet to the client. This allows the client to determine if the server is alive and well. It also allows the client to measure the round trip time (RTT) between the client and the server. It thus provides a similar functionality to the ping command-line utility (though using UDP rather than ICMP, Internet Control Message Protocol).

Copy the UDPPingServer.py program onto your account on our Tokyo-based VPS. The server program takes two optional command-line arguments. The first specifies the port number it listens on. The second specifies the percentage of ping requests to ignore. The latter can be used to simulate packet loss in the network so you can test to make sure your client is robust to such loss.

Ping client
Your job is to develop a UDP-based ping client that will provide periodic stats about the availability and latencies of the server. Your program UDPPingClient.py requires four command-line arguments: If the client is run with fewer that four command-line arguments, it prints out a helpful error message and exits:
% python UDPPingClient.py UDPPingClient.py <server name> <server port> <secs between> <output stats every>
Each ping request should be sent as a UDP packet with a payload of the letters a-z repeated 10 times (a total of 260 bytes of payload). The server should echo the exact text back to your client. Your client should first validate that the received message is exactly equal to the sent message (i.e. it was not corrupted in transit). Your client should also time (to millisecond accuracy), how long it took between right before the sending of the UDP packet to the right after the receipt of the response. This time period is the RTT for that particular ping. After each request-response cycle, the client should sleep for the number of seconds specified by the third command-line argument.

We suggest you first get the above working and validate with appropriate debug print statements. You should see a similar RTT from your program as returned by using the ping utility. You should also test to be sure your program doesn't crash if the server is setup to drop a certain percentage of packets.

We want our ping client to support reporting statistics about how the pinging has been going every so many seconds (e.g. once an hour). Add code to your program that triggers every so often based on the last command-line argument. When triggered, you should output a tab-delimited line of text containing the following pieces of information: Aside from the timestamp in the first column, round all statistics to two decimal places. All times should be reported in milliseconds. Be sure to reset all your statistic counter variables when the time period resets. Here is an example runs against a Tokyo server that was not randomly dropping any packets:
% python UDPPingClient.py 106.187.54.31 12000 1 10 2012-10-03 11:50:55.968347 10 184.81 0.51 184.20 185.79 0.00 0.00 2012-10-03 11:51:06.638566 9 184.65 0.48 184.17 185.64 0.00 0.00 2012-10-03 11:51:17.305699 9 184.36 0.30 184.04 184.93 0.00 0.00 2012-10-03 11:51:27.975108 9 184.46 0.40 183.99 185.22 0.00 0.00 2012-10-03 11:51:38.639626 9 184.29 0.21 184.04 184.72 0.00 0.00
Here is an example runs against a server on localhost that was dropping 10% of packets:
% python UDPPingServer.py 1234 10 & Server ready to receive on port = 1234, dropping 10% % python UDPPingClient.py localhost 1234 5 60 2012-10-03 11:55:33.711451 12 0.50 0.10 0.38 0.78 7.69 0.00 2012-10-03 11:56:41.728496 8 0.54 0.14 0.43 0.85 33.33 0.00 2012-10-03 11:57:52.748015 10 0.47 0.03 0.44 0.51 23.08 0.00 2012-10-03 11:58:54.764884 11 0.51 0.14 0.38 0.76 8.33 0.00 2012-10-03 11:59:56.778683 11 0.48 0.06 0.42 0.63 8.33 0.00
Note that the Berkley socket calls such as recvfrom() are blocking, they will wait forever for something to arrive. In the case of a dropped packet, you want your program to continue sending requests. You should set a timeout of 2 seconds on your socket communication. A request counts as having timed out if no response is received in this amount of time.

How do I measure the elapsed time between two events in Python? Here is a code snippet that calculates the elapsed milliseconds between two lines of code:
import datetime as dt ... start = dt.datetime.now() ... timeDiff = dt.datetime.now() - start elapsed = (timeDiff.days * 24 * 60 * 60 + timeDiff.seconds) * 1000 + timeDiff.microseconds / 1000.0
Will the stats dump interval be a multiple of the ping interval? Not necessarily. You can expect the dump interval to be sufficiently larger than the stats dump interval so at least a few pings occur in the time period. But you should just track the time elapsed since the last stats dump to determine when it is time to do the next one (since exactly how long each ping takes is effected by the RTT and timeouts).

If given a dump interval of 60 seconds and a ping every 5 seconds, do I need exactly 12 data points in that period? No. You may get fewer depending on the RTT of the network and how often packets are timing out.

Let's make an experiment
Once your program is working and tested, perform a 24-hour experiment measuring UDP performance between some client and the Tokyo server. You should send a ping request every 10 seconds and output statistics every hour (3600 seconds). Write a report of your experiment and submit an electronic document that I can read (Word, Open Office, or PDF). The report should contain the following:
Submission. Submit your programs UDPPingServer.py, your tab-delimited 24-hour result file, and your experiment report via Moodle. Be sure each submitted source file has the required header with your name, username, and a description of the program. Programs should use descriptive variable names and appropriate levels of commenting (explain at a high-level the goal of different sections of code).

Page last updated: October 06, 2013