Project Overview
In this project, you will implement a simplified Transmission Control Protocol (TCP) client and server that does a three-way handshake, a well-known protocol sequence used in communication networks. This project has three parts:
- Part A: The client and single-threaded server
In this part, you should implement the client and the server, with the server implemented as a single-threaded program. The client will be reused for part B and C.
- Part B: Multi-threaded server
In this part, you should improve your server implementation by making it concurrent with multithreading.
- Part C: Event-driven server
In this part, you should implement a single-threaded but concurrent server using event-driven techniques.
Do note that this is an individual assignment; you may not collaborate with others on this assignment. We encourage you to use Version Control in the provided course repository, but do note that this respository should be and remain private indefinitely. Please avoid publishing your project in a personal/public repository to maintain academic integrity.
Key Words for Specifications
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD,
SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.
Advice
In this project, you will learn and implement synchronous (3a, 3b) and asynchronous (3c) communication between the server and clients. Please make good use of TA hours, Open Office Hours, and Recitations. They are excellent supplements to the lectures and have many practical system programming tips to improve your project. We highly recommended that you read the instructions for each part first, read the manual pages for new system calls, participate in our recitations, and start early. We will hold 2 recitations: the first will focus on Part A and Part B, and the second will focus on Part C.
Please be aware that the example code provided for each part of this project only provides examples of certain features, and is NOT a starter template for each part of the project. The following table highlights the features that each example code demonstrates:
| Project example code | Features demonstrated in the example code |
| Part A | Socket communication |
| Part B | Use of pthread library |
| Part C | Asynchronous I/O |
Based on our past experience, asynchronous communication can be unintuitive and students need to have a different mindset to organize communication logic. This will be the main focus of the second recitation. Please budget extra time for this final project part as it is the most challenging.
Moreover, you are highly encouraged to utilize the course discussion forum to discuss the project with classmates and TAs. Before asking the question, please search in the forum to see if there are any similar questions asked before. If it is about a bug, check if it is covered in the Common Mistakes document. Please check all suggestions listed there. If you plan to ask about your code/implementation on the forum, please consider filling in the following template to make the communication efficient:
- GitHub URL:
- Description of Question:
- Expected Behavior: • Observed Behavior:
1 Project 3a: The Client and Single-threaded Server
Overview
For Part A, you will implement both a server and client which will communicate over the network by exchanging messages and checking that the messages are in the correct format.
1.1 Requirements
1.1.1 Source files and arguments
- You MUST implement two source files in this part: the client (tcpclient.c) and the server (tcpserver.c).
- You MUST provide a makefile that will create the executables tcpclient and tcpserver. You SHOULD include all and clean rules in your makefile.
- The client MUST take three arguments as input: server IP address, server port number, and an initial sequence number, in that order.
- The server MUST take a single argument as input: the server port number. The server MUST be listening on this port for the entirety of execution.
- The client and server SHOULD gracefully exit if a user provides an incorrect number of arguments. You MAY print a helpful message regarding the expected syntax.
1.1.2 Handshake Protocol
You MUST implement the following three-way handshake communication:
- The client MUST initiate communication and send the message HELLO X to the server, where X is an initial sequence number (one of the three arguments).
- The server MUST receive and print the HELLO X message from the client to standard output. The server MUST send a response HELLO Y to the same client. The value of Y MUST be X + 1. You MAY handle wrap-around (this edge case will not be tested or checked for, however).
- The client MUST receive the HELLO Y message from the server and print it to standard output. The client MUST check the received value of Y and compare it to the expected value of Y (namely, X + 1).
- If Y = X + 1, the client MUST send HELLO Z to the server, where Z = Y + 1.
After sending this message, the client MUST close the connection.
- If Y != X + 1, the client MUST print an error message to standard error that starts with ERROR, then close the connection. The error message MAY provide further details on the reason of the error.
- If the server receives the HELLO Z message from the client, the server MUST print it to standard output.
- If Z != Y + 1, the server MUST print an error message to standard error that starts with ERROR. The error message MAY provide further details on the reason of the error.
Regardless of the received message, the server MUST close the connection. The server MUST continue to listen for new connections and accept them.
1.1.3 End of Line characters
- The HELLO message MUST NOT contain the EOL character ‘\n’ when transmitted over the network.
- You MUST print each received message on a separate line.
- You MUST flush the output immediately after writing the HELLO message as described in the previous two items. This is because printing in Linux is buffered and may happen asynchronously. If a process does not exit gracefully, your intended prints may be lost. In the autograder, we terminate the server with SIGKILL, then evaluate the server output.
1.1.4 Miscellaneous
- You SHOULD follow the Coding Guidelines, which is in the Project Resources Module of Canvas.
- You SHOULD compile with the -g and -Wall flags.
- You SHOULD handle any warnings produced by the compiler.
- You MAY assume that the client and the server do not crash during the communication. That is, you do not need to consider the case where the network fails to send the complete message or drops network packets.
- You MUST ensure that your client and server do not crash during execution (e.g. segmentation faults due to string (mis-)management or errors from system calls)
- You MUST ensure that the format of all sent messages (e.g. HELLO X) is correct.
- You SHOULD check the return value for all system calls and report an error (this is to help you debug; we are not checking for any error messages outside of the handshake protocol).
- You SHOULD clear all buffers before using them.
- Your implementation MUST work in the course Docker container.
- You SHOULD NOT make any assumptions about the listening port number on the server.
- Generally, the server and a client in your implementation should work on any two hosts in the network. That being said, since you are running all within one virtual machine, you can assume the server is listening on a port of your choice (see the Requirements section above), and clients and the server all run on the same machine with the same IP. You MUST use the loopback address as the default IP address for the server and all clients for the purposes of grading.
- You MAY create a custom server signal handler for the SIGINT signal. If you choose to do this, the signal handler MUST end by terminating the server.
1.2 Example Output
Here is some example output using 121 as the starting sequence number.
//Server
HELLO 121
HELLO 123
//Client
HELLO 122
1.3 Suggested Approach
This is a suggested approach. You are free to implement the solution in any manner you want.
- Start with the server initially. In the main function, check the arguments and setup appropriate variables for them.
- Create the listening socket, bind it to the port, and begin listening on it. You should review the demo code for this module for an example. At this point, your server should start and not crash or exit. Send an interrupt signal to terminate the server.
- In a loop, continue listening for new connections and accept them. accept is a blocking system call, so the server will block here until a client connects.
- Start working on the client. As with the server, check the arguments and setup appropriate variables for them.
- Create a socket and have it connect to the server. At this point, you should be able to run the server followed by the client and see the client connect.
- Begin implementing the handshake protocol. Start by having the client construct the appropriate initial handshake message HELLO X and send it to the server. On the server side, recv the message and print it to the display. Now when you run the server and client, you should see the server print the client’s initial message.
- In the server, setup the response message (HELLO Y) and send it to the client.
- In the client, recv and print the server’s message.
- The client now needs to check if this message has the expected sequence number. If it is unexpected, print the error message; otherwise, construct the HELLO Z message and send it to the server. You can test the error handling by (temporarily) hardcoding the server to always send the wrong response.
- The client is now complete, so close the socket and end the program.
- The server has one final check to do: ensure the HELLO Z message has the expected sequence number. Handle both scenarios and close the socket to this client. Then return to the top of the loop for a new client.
1.4 Submission
- Your solution MUST compile when running make clean followed by make. Please do check this before submitting. Submissions that fail to compile will receive a 0.
- You MUST submit all source and header files, and the makefile, in a tarball (.tar.gz) to the Gradescope assignment CIT 5950 Project 3a.
- Your tarball SHOULD NOT contain compiled binaries or demo code files. • You have unlimited submissions until the due date specified by the syllabus.
1.5 Grading
Project 3a will be marked on five rubric items. The descriptions for these tests are in the The Autograder section.
There is no peer review for this assignment. You will not be marked on code style.
The score at the due date is final. Do note that they do not sync with Canvas immediately; the course staff must manually release them.
- Proxy Test : 20 points
- Load Test : 20 points
- Sequential Clients Test : 30 points
- Client Error Checking Test : 15 points
- Server Error Checking Test : 15 points
Total : 100 points








