Lab 3: Python SocketsFall 2024
This lab seeks to help introduce you to TCP sockets, and how to use them in Python, since you will be doing this in project 3. You will write a script that connects to a server, answers a few addition questions, then gets a secret code.
Useful Links
Setup
If you haven’t already, follow our Docker guide to learn how to set up Docker on your computer. You’ve probably already done this for previous labs and projects.
To get the code for this lab, create a repo using the GitHub template. Make sure to make this repo private. Clone the repo onto your system, then open it in VS Code. If you successfully set up Docker, you should be greeted with a pop-up in the bottom right asking you to reopen the directory in the development container; do so now! After some time taken to build the container, you should be greeted with the lab file in a directory and a terminal connected to the container (as shown in the Docker guide). If you’re having trouble at this point, please come to office hours or put up a post on Piazza describing in as much detail as possible what is going wrong—having a working Docker installation is essential for the course (which is why we’re making sure that it works in this lab!).
Background
You already have experience with HTTP, which is a protocol for communicating over the network. It is convenient, but it’s also quite limited. The only communication scheme it allows is for the client to send a complete message, then for the server to respond with a complete message.
TCP is a lower level protocol, which makes it a bit harder to work with, but a lot more flexible. At any moment, the client or the server can send the other a stream of bytes. This stream is guaranteed to arrive in order, but it may not arrive all at once. This allows the recipient to get started processing the data before the sender has even finished sending it.
Tasks
Overview
You will write a Python script that interacts with a server over TCP. The server will ask your script a few simple addition questions. If you answer them all correctly, it will give you a secret phrase that you will print out.
It may be helpful to reference the Python Socket Programming HOWTO guide
and the Python socket
module documentation while working on this lab.
Running the script
Your script should take 2 command line arguments, which tell it how to locate the server.
The first one is the hostname. The second one is the port number. When running your script
locally, use mathserver
and 8000
. You have to be inside the Docker container in order
to connect to the mathserver.
python3 lab3.py mathserver 8000
You can also run your script in the VS Code debugger.
Connecting to the Server
In order to use sockets in Python, you will have to import the socket
module:
import socket
Construct a new socket:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
The socket will be automatically closed as soon as you leave the
with
-statement. Make sure that you only interact with sock
inside the
with
-statement.
Then connect the socket to the server:
sock.connect((HOST, PORT))
Do not hardcode HOST
and PORT
. The Autograder will use different values
than what you use in your Docker container.
Communicating with the Server
Questions & Answers
As soon as you connect to the server, it will send you your first addition question.
To receive the data it has sent you:
data = sock.recv(4096)
Reminder: TCP transfers data as a stream. This means that any “message”
the server sends you isn’t guaranteed to arrive all at once. You may need to
call sock.recv
multiple times in order to get the full “message”.
Each time you call sock.recv
, you’ll be reading new data. Make sure
to save the data from each call so you can concatenate it all together.
The question will be formatted as the following 9 bytes:
+---+---------------------------+---------------------------+
| Q | 4-byte big-endian integer | 4-byte big-endian integer |
+---+---------------------------+---------------------------+
The Q
byte indicates that this is a question. You will need to covert into two
integers. Add these integers together, then convert the sum into 4 bytes (using
big-endianess).
Now that you have your answer in the form of bytes, send it back to the server:
sock.sendall(answer)
If you get the answer wrong, the server will close the connection early.
This question and answer process will repeat a random number of times. Once it’s done, the server will send you a secret phrase instead of a question.
Secret Phrase
Receiving the secret phrase is exact the same process as receiving a question:
data = sock.recv(4096)
The secret phrase will be formatted as the following 9 bytes:
+---+----------------------+
| S | 8-byte secret phrase |
+---+----------------------+
You can tell that this is a secret phrase and not a question because it begins with
an S
byte instead of a Q
byte.
Print this 8-byte secret phrase.
Closing the Connection
If you put the socket inside a with
-statement, it will automatically be
closed as soon as you leave.
If you didn’t put the socket inside a with
-statement, you can close it
manually with:
sock.close()
Submission
Submit the following files to the Autograder by the deadline:
lab3.py