Lab 10 - Socket Programming: Multiple Clients
Expand for the usual lab directions
- Submit your completed lab online to CourSys (not Canvas, not GitHub).
- Labs are marked on completion, not correctness, so complete each part to the best of your ability and learn.
- Lab is due Sunday and may be submitted up to 3 days late. Further extensions possible only in exceptional cases.
- It is recommended that students attend in-person lab sections for lots of support!
- You are invited to come to any (or more than one) lab section.
- There is no need to attend the section you are enrolled in.
- There is no need to attend any lab sections: there is no attendance taken.
- You can complete the lab on your own time or own computer if you like.
- Time suggestions are given here to guide students who are working on the lab during lab times. However, the entire lab must be completed by everyone for marks.
- While completing these labs, you are encouraged to help your classmates and receive as much help as you like. Assignments, however, are individual work and you must not work with another person on assignments.
- I recommend coming to the lab and working with someone.
- Failing that, I recommend getting together with someone in the class outside of lab time to work through the lab together.
- Failing that, you are welcome to complete the lab exercise without any collaboration.
- Each student must submit their lab to get marks.
- Academic honesty expectations for labs are that each student types their own lab solution. It is OK to share ideas and help each others with specific coding issues and design. It is not permitted to submit another student's file for credit.
- If using CSIL lab PC:
- [Only CSIL PC] If in Windows, reboot to Linux; while booting, select Ubuntu from boot menu.
- [Only CSIL PC] Don't setup GitHub tokens in the
cmpt201
container because it may be shared with other users. - [Only CSIL PC] Delete any possible previous docker container before starting the lab:
docker rm cmpt201
- [Only CSIL PC] When done your lab, copy your solution out of the container, then execute the above docker command to delete your docker container to leave it clean for the next user.
- You do not need to use
.record
Goals for this lab
- Apply your understanding of multi-threading and synchronization to client-server sockets.
- Understand a parallel flow of information to a server.
- Able to stop a thread.
Prerequisite Skills for This Lab
- Linux socket programming.
- C Skills
- Able to use structs, arrays, pointers
- Able to compile, run, and debug C programs using CMake.
Task 1: Download & Compile
- Clone the Lab 10 starter project
- Compile and run the program. Use multiple terminals:
- One for
nvim
: I suggest opening all .c files at once (nvim *.c
). You can switch between them using the commands:b1
and:b2
. - One for running the server: use
build_and_run_server.sh
. - One for running multiple clients: use
build_and_run_clients.sh
. - You only need to run
cmake
once to generate the makefiles in/build
, assuming you don't create additional .c files. - Each time you edit
server.c
orclient.c
, re-run the appropriatebuild_and_run_xxxxxx.sh
script.
- One for
- Copy-and-paste the following questions into the top of the provided
server.c
, and then answer them. You can run the code and read the code to discover the answers./* Questions to answer at top of server.c: (You should not need to change client.c) Understanding the Client: 1. How is the client sending data to the server? What protocol? 2. What data is the client sending to the server? Understanding the Server: 1. Explain the argument that the `run_acceptor` thread is passed as an argument. 2. How are received messages stored? 3. What does `main()` do with the received messages? 4. How are threads used in this sample code? */
Task 2: Server Implementation
Complete the implementation for the server (server.c
) so that..
- In server.c's
main()
function, find the// TODO
for waiting until enough messages are received.- Add code to wait until the number of messages received is at least
MAX_CLIENTS * NUM_MSG_PER_CLIENT
. - OK to use a busy wait here if you like (loop that continuously re-checks it).
- Be careful about critical sections. You'll need to use a mutex to safely read the number of messages.
- Add code to wait until the number of messages received is at least
- In server.c's
run_acceptor()
, find the// TODO
for creating the threads.- Add new code to launch a new thread for each connected client.
- Hint: All necessary parameters to
pthread_create()
are created and ready to pass in. - Remember to count the number of clients connected (
num_clients
). - When you accept a new connection, print "Client connected!\n" to the screen.
- In server.c's
run_client()
, find the// TODO
.- Call
add_to_list()
, passing in the correct arguments to add the newly created node to the list. - Hint: All parameters are readily available to just be passed in.
- Ensure you are writing thread-safe code. You'll need to lock something before calling
add_to_list()
.
- Call
- Have your program cleanly shut-down threads:
- Find the TODOs in
run_acceptor()
. - To set the stop flag, you are looking for the
run
field in the clients. - You'll need to cleanup the thread and the socket.
- Hint: use
pthread_join()
andclose()
respectively.
- Find the TODOs in
- Answer this question in the top of your server.c:
- Explain the use of non-blocking sockets in this lab.
- How are sockets made non-blocking?
- What sockets are made non-blocking?
- Why are these sockets made non-blocking? What purpose does it serve?
- Explain the use of non-blocking sockets in this lab.
- Output Sample
- Server side with 3 clients connecting:
Client connected! Client connected! Client connected! Client connected! Not accepting any more clients! Collected: Hello Collected: Apple Collected: Car Collected: Green Collected: Dog Collected: Hello Collected: Hello Collected: Hello Collected: Apple Collected: Apple Collected: Apple Collected: Car Collected: Car Collected: Car Collected: Green Collected: Green Collected: Green Collected: Dog Collected: Dog Collected: Dog Collected: 20 All messages were collected!
- Running 3 clients at once.
labs/lab10❯ ./build_and_run_clients.sh [ 33%] Built target server [ 66%] Built target client [100%] Built target server_sol Sent: Hello Sent: Hello Sent: Hello Sent: Hello Sent: Apple Sent: Apple Sent: Apple Sent: Apple Sent: Car Sent: Car Sent: Car Sent: Car Sent: Green Sent: Green Sent: Green Sent: Green Sent: Dog Sent: Dog Sent: Dog Sent: Dog
- Server side with 3 clients connecting:
3. [Optional] Challenges
- Optional: Lots of clients
- Launch many many clients to try and connect to the server. How good is performance as you scale the number of clients? How can you measure this automatically?
- Optional: Switch to using an atomic integer (
#include <stdatomic.h>
) for the count of number of messages received. - Optional: Switch to using a condition variable to track number of messages received.
Submission
Create a new file name lab10.c
which contains the code from:
client.c
- followed by the code from
server.c
.
Submit just your lab10.c
C code to CourSys by Sunday midnight. The file name must be an exact match to what CourSys is expecting, otherwise it won't accept it. Remember you can submit up to 3 days late with no penalty if needed (but please plan to get it done on time to stay up to date on the course!)
Submissions will be marked for completion. You do not need to complete any optional steps.