辅导 data程序、讲解 Python编程设计
            
                Coursework 1 – Network Application Development 
Coursework Weight: 20% 
 
In this coursework, you will develop several networking-based applications. These are designed 
to increase your competency in developing socket-based applications and increase your familiarity 
with several key technologies and measures. These are widely used and commonly deployed to 
evaluate networks and provide services. 
 
During this practical, you will become familiar with network sockets and begin to understand 
how they are used. Sockets are a programming abstraction designed to assist us in building 
applications that use the network. We can treat these the same as any other resource; writing 
to a socket sends a packet into the network, whilst reading from a socket provides us with the 
contents of a packet. We can do this in much the same way as we would read and write to any 
file found on the local filesystem. 
 
Practical Lab Structure 
 
Practical 1 is split into two parts: Tasks 1 and 2. We also recommend that you complete the 
partially implemented Traceroute class before starting Task 1. For more, details, see Example 
Code 2 section on page 5. 
 
For the tasks assessed, you will be awarded points for meeting certain criteria. These are 
outlined in more detail within each task description at the end of this document. You are 
encouraged to progress as far as possible with each task. However, note that Tasks 1 and 2 are 
independent; attempting both is advised, even if you do not fully complete each. 
 
This course uses a dedicated virtual machine image for these labs. 
 
Running the Code Locally 
 
Running the code locally on your machine (directly and without a VM) is also possible. To do 
so, you will need to install Python 3 (version 3.10 or newer is recommended). As this task does 
not use any external libraries (see ‘Python Library Usage’ section below), this should be 
relatively easy to achieve. 
 
Details on how to install Python can be found here: https://www.python.org/downloads/ 
 
There are some caveats with this approach, though (hence why we provide the virtual machine). 
Although the same Python code will run regardless of the environment, the underlying 
implementation (and therefore) behaviour can be different, including for many of the networkrelated
libraries used in this practical. Particularly on the Windows platform (rather than MacOS 
or Linux), the results may be different. 
 
Given the multitude of potential discrepancies and variances that may occur when running code 
locally, we will not provide direct support for the method; only the virtual machine-based 
approaches will be supported by the teaching team. 
 
 
 
 
 
SCC. 231 Computer Networks and Systems 1  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
Note that for marking, the provided virtual machine will (and must) be used. It is not an 
acceptable excuse to claim that it worked on your machine, so at the very least, please ensure 
that it runs on the provided virtual machine image (using one of the methods described 
in the sections below or above) before submitting. 
 
Using the SCC 231 Virtual Machine 
 
To access this, please use the following link and select the ‘SCC 231’. 
 
https://mylab.lancaster.ac.uk/ 
 
The VM can be accessed via a browser or a downloadable client. 
 
Provided/Skeleton Code 
 
To help you structure your code and get started with each task, we have provided you with a 
skeleton code (NetworkApplications.py), which is available on the SCC.231 Moodle page. This 
file should eventually contain all the code you have developed in this lab and will be the one 
submitted at the end of your work. It contains a structure for the code, including some helper 
functions and empty classes. It also contains pseudocode for some of the tasks to get you started. 
 
Firstly, there is a function included to parse command line arguments given to the script 
(setupArgumentParser). This includes determining which function is called (ping, 
traceroute, mtroute, web, proxy), as well as additional parameters used for each 
task. Some of these may be optional, particularly if they are part of the additional features 
associated with each task. 
 
 
The code also includes the NetworkApplication class, which will be a parent to the 
classes that you will develop in the coursework. It contains some useful methods that are 
common across tasks. This includes the checksum function, which calculates a checksum to 
be used in an ICMP packet. Furthermore, it also includes two methods which are used to print 
out the results generated ping (see the Example Code 1 section below): printOneResult and 
printAdditionalDetails. 
 
Finally, it also includes five classes: ICMPPing, Traceroute, MultiThreaded 
Traceroute, WebServer and Proxy). In the case of ICMPPing and WebServer, they 
include the complete code as examples for you to study. The Traceroute class is partially 
implemented; it contains a fully functional UDP traceroute, but not ICMP traceroute. 
 
These classes inherit the NetworkApplication class, allowing you to use the parent’s 
helper methods (checksum, printOneResult, printAdditionalDetails, and 
printMultipleResults). These can be called from the child classes. For more details on 
inheritance in Python, see here: 
 
https://docs.python.org/3/tutorial/classes.html#inheritance 
 
Each class contains an __init__ method, called when the object is created (which is done 
once the command line arguments have been parsed, in this case). This is the starting point for 
writing the code in each class, but additional methods can be created as required. Important: 
changing the method signature for any of these __init__ functions will result in zero 
marks, so please retain all the arguments, including the args object. 
 
 
SCC. 231 Computer Networks and Systems 2  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
To be clear: you can add new methods and code to each of the main classes: Traceroute, 
MultiThreadedTraceroute and Proxy (and even to the fully-implemented classes Ping 
and Webserver), but the remaining structure, methods and code must remain intact. 
 
Running your Python script 
 
Once you have the virtual machine setup, you are ready to begin. For this practical, you will 
be building your applications using Python 3 (as installed on the virtual machine). 
 
To run a Python script, open a Terminal window and navigate to the directory in which the 
file you want to run is located. To run the script, simply use the following command: 
 
➢ python3 NetworkApplications.py 
 
The above will print the usage information for this program. Please note the use of 
python3 rather than python: the default command refers to Python 2.7, which we are 
not using in this course. Using this will result in a different outcome and potential 
incompatibilities. 
 
When you start this task, the provided code will run successfully and print the help 
information but do nothing. 
 
Python Library Usage 
 
You are not expected to use any external libraries for this practical; doing so is strictly prohibited. 
All tasks can be achieved fully with the use of standard Python libraries. 
 
We are also aware of a number of network and IP-orientated libraries that are included within 
the standard Python distribution. These could potentially be used in different ways to assist in 
your implementation. However, as we are trying to build your understanding around the 
fundamentals of computer networks, we ask that you do not use these for this practical, either. 
 
The teaching team believes it is vitally important that you grasp the technical details behind many 
of these libraries, which do a good job of abstracting and obscuring the details. It is, of course, 
perfectly acceptable to use these libraries in any future software development you may do, 
whether this be as part of an upcoming course module or even after graduation. 
 
By following the provided structure and guidance, you will not need to use any of these. If you 
are in any doubt about whether or not you can use a particular library, please contact 
the course tutors to confirm. 
 
Submission and Assessment 
 
The submission for all work completed in this practical is due by 4 pm on December 13
th
 
(Friday, Week 10). All code must be included in a single file titled NetworkApplications.py and 
submitted on Moodle. 
 
 
 
 
 
 
SCC. 231 Computer Networks and Systems 3  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
Automated Testing 
 
When marking your code, we will be using an automated testing tool. For the automarking tool 
to work, it is vital that you follow the guidance described in the ‘Provided/Skeleton Code’ and 
‘Submission and Assessment’ sections regarding modifying provided classes, methods and 
filenames. 
 
Failure to adhere to this will result in loss of marks and possibly a zero mark to be awarded. If 
you are in any doubt about whether a change or modification is acceptable, please contact the 
teaching team. 
 
Example Code I: ICMP Ping 
 
A ping client implementation is provided in the skeleton code. We have covered ping in week 2 
(third lecture). Remember that ping is a tool used to measure delay and loss in computer networks. 
It does this by sending messages to another host. Once a message reaches that host, it is returned to 
the sender. We can determine the sum of nodal delays in the network by measuring the amount of 
Round-Trip Time (RTT) taken to receive that response. Similarly, by tracking the responses returned, 
we can determine if any have been lost in the network. 
 
ping traditionally uses Internet Control Message Protocol (ICMP) messages to achieve this 
behaviour. The example code sends echo request messages (with an ICMP type code of 8). These 
requests are useful to us because on reaching the client, the client will respond with an echo reply 
message (with an ICMP type code of 0). By timing the period of time elapsed between sending 
the request and receiving the reply, we can accurately determine the RTT between the two hosts. 
 
In general, you can get help with running each of the classes: traceroute, mtroute (multithreaded 
traceroute), webserver, and proxy by issuing a --help (or -h) argument in the terminal: 
 
➢ python3 NetworkApplications.py ping --help 
Or 
➢ python3 NetworkApplications.py ping -h 
 
which will print usage information. In the case of ping, python3 NetworkApplications.py ping --
count 5 --timeout 1 lancs.ac.uk will send five ping probes to Lancaster university server with one 
second timeout on the receipt of responses. Note that the count and timeout are optional 
arguments and their default values are defined in setupArgumentParser method. 
 
A timeout on a socket defines the maximum time the socket will wait while trying to receive 
data before raising an exception. If data is not received within the specified timeout period, the 
recv and recvfrom methods will throw a socket.timeout exception. This ensures that your 
program does not get stuck indefinitely waiting for a response and allows you to handle network 
delays or packet loss more effectively. You can set the timeout using socket.settimeout(seconds). 
 
It is possible to use both socket.SOCK_RAW and socket.SOCK_DGRAM when creating 
sockets. SOCK_RAW requires privileges, as it gives you a huge amount of control and power 
over the type and content of packets sent through it. As such, it requires sudo to work.
In 
normal circumstances, a non-privileged version would probably be preferable; you don't 
always have sudo privileges on a system. This is where SOCK_DGRAM comes in. However, it 
appears that SOCK_DGRAM, when used to specifically to send ICMP packets, is also a privileged 
operation within some flavours of Linux (and on the provided VM). 
 
SCC.231 Computer Networks and Systems 4 
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
For the purposes of this practical, it is therefore recommended that you use SOCK_RAW. Note: 
normally, using SOCK_RAW requires sudo privileges. On the SCC.231 VM, you can run your 
code (and use raw sockets) without sudo, but on another machine, you will need sudo access. 
 
The ICMP header contains both an identifier and a sequence number. These can be used by your 
application to match an echo request with its corresponding echo reply. It is also worth noting that 
the data included in an echo request packet will be included in its entirety within the corresponding 
echo reply. Use these features to your advantage. 
 
Example Code 2: UDP Traceroute 
 
We have also provided you with a partially implemented (a single-threaded) Traceroute. In particular, 
the UDP traceroute implementation is provided. You are encouraged to add the ICMP Traceroute 
implementation to make this a fully functional Traceroute tool. Please carefully go through the 
provided UDP implementation before you start working on the ICMP traceroute. Although, the ICMP 
traceroute is not marked, we strongly recommend that you work on ICMP traceroute, as your 
code for this part can be re-used in Task 1: MultiThreadedTraceroute. 
 
As discussed in Lecture 3 (week 2), traceroute measures RTT between the host and each 
hop along the route to a given destination. By default, this tool uses UDP messages with a TimeTo-Live
(TTL) value initially set to 1. This ensures we get a response from the first hop, the 
network device closest to the host on which we run the script. When the message arrives at this 
device, the TTL counter is decremented. When it reaches 0 (in this case, at the first hop), the 
message is returned back to the client with an ICMP type of 11. This indicates that TTL has been 
exceeded. As with the previous task, by measuring the time taken to receive this response, RTT 
can be calculated at each hop in the network. This process can be repeated, increasing the TTL 
each time, until we receive a destination unreachable message (with an ICMP type of 3). This tells 
us that we have reached the destination, so we can stop sending traceroute probes. 
 
To run Traceroute, you can check its usage by: 
 
➢ python3 NetworkApplications.py traceroute --help 
 
The traceroute expects a hostname (similar to ping), and you can provide optional parameters. As 
an example, to run UDP traceroute to lancs.ac.uk, do: 
 
➢ python3 NetworkApplications.py traceroute --protocol udp lancs.ac.uk 
 
or 
 
➢ python3 NetworkApplications.py traceroute -p udp lancs.ac.uk 
 
The ICMP variant of traceroute operates similarly but uses ICMP Echo Request (Type 8) messages 
instead of UDP packets. The Time-To-Live (TTL) value is still incremented with each probe, and when 
the TTL expires at each hop, the router sends back an ICMP Time Exceeded (Type 11) message. The 
round-trip time (RTT) is measured based on the time it takes for this response to return. Once the 
probe reaches the final destination, an ICMP Echo Reply (Type 0) is received, indicating that 
traceroute has successfully completed the path discovery. 
 
When you eventually implement ICMP traceroute, you should be able to run it by: 
 
 python3 NetworkApplications.py traceroute -p icmp lancs.ac.uk 
 
 
SCC.231 Computer Networks and Systems 5
  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
You can run the real traceroute tool using the traceroute command on the terminal. Note that by 
default, traceroute uses UDP probes. To send ICMP probes, you must use the -I flag: 
 
➢ traceroute -I lancs.ac.uk 
 
Example Code 3: Web Server 
 
Web Servers are a fundamental part of the Internet; they serve the web pages and content that we 
are all familiar with. You will be learning more about web servers and the operation of the HTTP 
protocol in Lecture 6: Application Layer II: Web & HTTP Basics (week 3, lecture 6). Fundamentally, a 
web server receives an HTTP GET request for an object (usually a file) located on the web server. 
Once it receives this request, the web server will respond by returning this object back to the 
requester. 
 
The Web Server differs from the ICMP Ping application in that it will bind to an explicit 
socket, identified by a port number. This allows the Web Server to listen constantly for 
incoming requests, responding to each in turn. HTTP traffic is usually bound for port 80, with 
port 8080 a frequently used alternative. For the purposes of this application, we suggest you 
bind to a high-numbered port above 1024; these are unprivileged sockets, which reduces the 
likelihood of conflict with existing running services on the virtual machine. 
 
For example, a request with a URI of 127.0.0.1:8080/index.html, will serve a file 
name index.html found in the same directory as the Python script itself. The URI is broken 
down as follows: 
 
• 127.0.0.1: Hostname of web server 
 
• 8080: Port number that web server has bound to 
 
• index.html: File to be served 
 
On successfully finding and loading the file, it will be sent back to client with the appropriate 
header. This will contain the Status-Code 200, meaning that the file has been found OK, and that 
it will be delivered to the client as expected. This implementation only serves files from the 
same directory in which the Python script is executed. To start the WebServer, simply do: 
 
➢ python3 Network Applications.py web -p 8081 
 
Then copy the following URI and paste it into the address bar of your favourite browser: 
127.0.0.1:8081/index.html. You must also store an index.html file in the same folder where 
you run your script. A dummy index.html file is provided in Moodle. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SCC. 231 Computer Networks and Systems 6 
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
 
Task 1: A Multithreaded Traceroute 
Weight: 50% of the total mark for coursework 1 
 
Building on example code 2, this task aims to create a multithreaded traceroute tool. 
 
Implementation Tips 
 
In general, you can find lots of information about the socket library documentation: 
 
https://docs.python.org/3/library/socket.html 
 
In this task, you will implement a multithreaded version of the traceroute tool (mtroute), which 
sends probes and receives responses in parallel using separate threads. A skeleton code is 
provided in the MultiThreadedTraceRoute class to help you get started. Your task is to complete 
the implementation of mainly the two methods: send_probes and receive_responses, using the 
ICMP and UDP protocols (you can also modify the __init__ method and include additional 
methods as you need). 
 
Your implementation must: 
• Use one thread to handle the sending of traceroute probes, incrementing the TTL as 
described earlier. 
• Use another thread to handle the reception of responses, calculating the round-trip 
times (RTT). 
• Ensure thread safety by using locks for shared data, and use thread events to signal when 
sending is complete (which is already provided in the skeleton code). 
 
Your final implementation should display the traceroute results, including the IP of each hop 
and the RTT, using the printMultipleResults method. 
 
Debugging and Testing 
 
As with the previous task, every host on the path to your chosen destination should respond 
to your probes. In reality, these probes are often filtered, including within the lab network. As a 
result, it is especially difficult to test this tool with a remote host. Instead, it is suggested that you 
initially test with a closer endpoint that is reachable: lancs.ac.uk. Although the number of hops is 
small (~5), it can still be used to demonstrate the working of your application. If you run your 
script whilst attached to a different network, such as at home, your results will likely differ. Once, 
traceroute to lancs.ac.uk works, you should also test destinations such as google.co.uk that are 
farther away. 
 
To run UDP multithreaded traceroute with lancs.ac.uk as the target: 
 
➢ python3 NetworkApplications.py mtroute -p udp lancs.ac.uk
 
 
To run the ICMP version of the multithreaded traceroute, simply update the -p option: 
 
➢ python3 NetworkApplications.py mtroute -p icmp lancs.ac.uk 
 
 
 
SCC. 231 Computer Networks and Systems 7  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
Note that your implementation must configure a timeout period to ensure that your program 
does not get stuck indefinitely waiting for a response. Please see the traceroute implementation 
on how to configure a timeout. 
 
The threading library is imported into the skeleton code. For more details on the use of 
threading, please refer to: https://docs.python.org/3/library/threading.html 
 
Wireshark can be used to inspect the packets leaving your application. Comparing these to 
those created using the original traceroute utility will provide a meaningful comparison. 
 
Marking Criteria 
 
The marks will be awarded for ensuring: 
 
1) A multithreaded UDP (30%) and ICMP (40%) traceroute implementation that sends a train 
of probe packets while simultaneously receiving and processing responses. (70%) 
 
Note I: Your implementation will be tested on the SCC.231 VM with at least two destinations: 
lancs.ac.uk and another one such as google.co.uk. The automarker will inspect the packets sent 
by your program to determine whether your implementation is correct; that is, the packet 
formats, sequence number handling, TTL management, and so on are accurate. 
 
Note II: your program must use the --protocol(or -p) positional argument to configure 
the protocol from the command line. The configurability is required for the automarker to test 
both protocols. 
 
2) Similar to the original traceroute utility, display three delay measurements for each 
node between your machine and the chosen destination. You are advised to use the 
printMultipleResults method in the skeleton code to print the output. (30%). 
 
Note III: Your final submission should not print extra (e.g., debugging) information other than 
the traceroute output. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SCC. 231 Computer Networks and Systems 8  
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
 
Task 2: A Web Proxy 
Weight: 50% of the total mark for coursework 1 
 
Building on the Web Server example, this task concerns building a Web Proxy. A Proxy operates 
similarly to a web server, with one significant difference: once configured to use the Proxy Cache 
application, a client will make all requests for content via this proxy. Normally, when we make a 
request (without a Web Proxy), the requests travels from the host machine to the destination. The 
Web Server then processes the request and sends back a response message to the requesting client. 
 
However, when we use a Web Proxy, we place this additional application between the client 
and the web server. Now, both the request message sent by the client, and the response message 
delivered by the web server, pass through the Web Proxy. In other words, the client requests 
the objects via the Web Proxy. The Web Proxy will forward the client’s request to the web 
server. The web server will then generate a response message and deliver it to the proxy server, 
which in turn sends it to the client. The message flow is as below: 
 
 
As with the Web Server, your Web Proxy application is only expected to handle 
HTTP/1.1 GET requests. Similarly, the Web Proxy will also bind to a specific port (this can 
be the same as the Web Server) and continue to listen on this port until stopped. 
 
Please ensure that all code for this task is included in the Proxy class. 
 
Debugging and Testing 
 
As with the webserver, there are a number of ways to test your Web Proxy. For example, to 
generate requests using curl, we can use the following: 
 
curl neverssl.com --proxy 127.0.0.1:8000 
 
This assumes that the Web Proxy is running on the local machine and bound to port 8000. 
 
In this case, the URL requested from the proxy is neverssl.com. 
 
A caveat when testing your Web Proxy: some websites have enabled HTTP Strict Transport 
Security (HSTS) (RFC6797). This forces clients (including both curl and a web browser) to use 
HTTPS rather than HTTP. HTTPS is a secure version of HTTP, but we will consider this out of 
the scope of this practical. 
 
Thanks to the proliferation of HTTPS (this is a good thing, just not for this practical!) the list 
of live websites you can test the Proxy with is quite limited. A few include: 
 
 
 
 
 
SCC. 231 Computer Networks and Systems 9  
 
 
Practical 1 Network Application Development Michaelmas Term, 2024 
 
 
• http://neverssl.com (see above) 
 
• http://captive.apple.com 
 
It is also possible to run a webserver locally on your virtual machine and test it from that. This 
could be the web server implementation provided in the code. Alternatively, Python also has a 
simple implementation that can be run directly from the terminal: 
 
https://docs.python.org/3/library/http.server.html 
 
As with the other tasks, Wireshark can be used to capture and investigate packets sent to and 
from your proxy. 
 
Marking Criteria 
 
For this task, marks will be awarded: 
 
1) A correctly implemented Web Proxy. You are expected to test the functionality of your 
Proxy using curl, as shown above. Note that you are not expected to use a website with 
HSTS enabled (see above). (60%) 
 
 
2) Binding the Web Proxy to a configurable port, defined as an optional argument (use 
port positional argument). (10%) 
 
 
3) Object caching: A typical Web Proxy will cache the web pages each time the client makes 
a particular request for the first time. The basic functionality of caching works as follows. When 
the proxy gets a request, it checks if the requested object is cached, and if yes, it returns the 
object from the cache, without contacting the server. If the object is not cached, the proxy 
retrieves the object from the server, returns it to the client and caches a copy for future 
requests. In practice, the proxy server must verify that the cached responses are still valid and 
that they are the correct responses to the client's requests. You can read more about caching 
and its handling in HTTP in RFC2068. Add the simple caching functionality described above. 
You do not need to implement any replacement or validation policies. Your implementation, 
however, will need to be able to write responses to the disk (i.e., the cache) and fetch them 
from the disk when you get a cache hit. For this you need to implement some internal data 
structure in the proxy to keep track of which objects are cached and where they are on the 
disk. You can keep this data structure in the main memory; there is no need to make 
it persist. (30%) 
 
Note: If you implement caching, ensure that your program does NOT use absolute paths (e.g., 
/home/Alex/project/cache) to the location of your cache file or folder. Doing so will not be 
compatible with automarking and result in zero marks. Instead, you must use relative paths 
(e.g., ./cache or subdir/cache). 
SCC. 231 Computer Networks and Systems 10