**Assignment 11: Networking** # Learning Goals - Learn how to write networked programs. - Gain experience with TCP sockets. # Grading Walk-Throughs This assignment will be graded as pass/needs-revisions by a TA. To pass the assignment, you must 1. Complete the assignment and submit your work to gradescope. - You should start this assignment in class on the day shown on the calendar. - **Complete the assignment as early as possible**. 2. Schedule a time to meet with a TA prior to the deadline. - You must book a time to meet with a TA - Sign-up on the Google Sheet **with at least 36 hours of notice**. - Contact your TA on Slack after signing-up. - All partners must meet with the TA. If you can't all make it at the same time, then each of you needs to schedule a time to meet with the TAs. 3. Walk the TA through your solutions prior to the deadline. - Walk-throughs should take no more than 20 minutes. - You should be well prepared to walk a TA through your answers. - You may not make any significant corrections during the walk-through. You should plan on making corrections afterward and scheduling a new walk-through time. Mistakes are expected--nobody is perfect. - You must be prepared to explain your answers and justify your assumptions. TAs do not need to lead you to the correct answer during a walk-through--this is best left to a mentor session. 4. The TA will then either - mark your assignment as "pass" on gradescope, or - mark your assignment as "needs-revisions" and inform you that you have some corrections to make. 5. If corrections are needed, then you will need to complete them and then schedule a new time to meet with the TA. - You will ideally complete any needed revisions by the end of the day the following Monday If you have concerns about the grading walk-through, you can meet with me after you've first met with a TA. # Overview For this assignment, you will implement a simple client-server messaging system that will send messages back and forth over the Internet. You should complete this assignment with a partner. Let me know if you want help finding one! Starter code is available on the server: ~~~bash tar xvf /data/A11-Networking.tar ~~~ You'll find the following files in the archive: `imclient.c`, `imserver.c`, and `Makefile`. **Only one process can be bound to a given port at a time. To handle contention (where multiple processes want to use the same port) you will each be assigned a port.** You can find the list of ports in the Port Numbers section. Both the client and server will run on the machine for now. I'll look into make this more interesting next week! # Tasks Your tasks are to implement a client and a server that exchange messages over the network. You will use TCP sockets to implement this task; a summary of the TCP socket life-cycle, along with descriptions of the relevant functions, is given in section TCP Sockets. ## Task 1: The Server Let's start with the server side. The server will take one program argument: a port number. On startup, the server will 1. gather information about itself (`getaddrinfo`), 2. open a socket (`socket`), 3. bind the socket to the given port (and the computer's IP address) (`bind`), 4. listen for incoming connections (`listen`), and 5. accept a client connection when one is made (`accept`). Now it will enter a chat loop in which it 1. waits for (and receives) a message from the client (`recv`), 2. prints the message to `stdout`, 3. reads a line from `stdin`, and then 4. sends that response to the client (`send`). When the client closes the connection, the server will close its open sockets with `close`. ### Demo When your server is completed, you can test it with the `nc` (network concatenate command). If you do not see an animation above this line (or if you see the animation but you don't see the progress bar), you will need to refresh the page (sometimes more than once). Or you can go directly to the player: https://asciinema.org/a/491106 ## Task 2: The Client The client will take two program arguments: an IP address (the IP address of the computer the server code is running on) and a port number (the port number the server is using). The client will 1. gather information about the server (`getaddrinfo`), 2. open a socket (`socket`), and then 3. initiate a TCP connection with the server (`connect`). Once a connection has been established, the client will enter a chat loop in which it 1. reads a line from `stdin`, 2. sends the message to the server (`send`), 3. waits for a response from the server (`recv`), and then 4. prints that response to `stdout`. If the line read from `stdin` is `"bye\n"`, then the client will break the loop and close its socket (`close`). This should signal to the server that it should shut down. ### Demo A sample interaction between client and server shown below: If you do not see an animation above this line (or if you see the animation but you don't see the progress bar), you will need to refresh the page (sometimes more than once). Or you can go directly to the player: https://asciinema.org/a/491107 # Port Numbers Partners can use whichever port they'd like. Name | Port -----|----- AdLi | 8930 AlMo | 8932 BeLu | 8934 CaFr | 8936 ChSu | 8938 DaDa | 8940 ElLi | 8942 EmTo | 8944 EmZh | 8946 GuTh | 8948 HaMa | 8950 InTs | 8952 NiMo | 8954 RoCo | 8956 SaSa | 8958 SeKw | 8960 ShZh | 8962 SuHa | 8964 TaXi | 8966 WiXu | 8968 # TCP Sockets The socket interface implements standards for "low-level" networked programs. Programs that work with TCP sockets all follow the same pattern. First, the server opens a socket and binds it socket to its IP address (or one of its IP addresses, if the computer has multiple) and to some specified port number. Many of the lower port numbers are reserved for particular types of applications (and might already be in use). For your own work, I'd recommend that you bind to a port number above 8000; you have been assigned a port for this assignment. The server then listens for incoming connections. Accepting an incoming connection opens a **new** socket file descriptor, which is then used to read and write over the TCP connection. When the client starts up, it opens a socket and connect to the server using the server IP address and the port associated with the listening socket. It then reads and writes to the server using this socket. This design pattern is summarized in the diagram below.  Note: the following descriptions are not complete, they are just intended to give you some hints for getting started. You will probably find yourself needing to look at the full socket documentation. One amazing resources is [Beej's Guide to Network Programming](https://beej.us/guide/bgnet/html/). ## Opening a Socket To open a socket, you need to specify the type of IP address you will use and the type of socket you will use. The value for IPv4 addresses is `AF_INET` and the value for TCP sockets is `SOCK_STREAM`. In C, this looks like ~~~c int sock_fd = socket(AF_INET, SOCK_STREAM, 0); ~~~ ## Binding a Socket Before you can use a socket, you need to bind it to an IP address and a port. It is good practice to not hard-code the IP address of your computer (as this will likely change!) and instead use an IP address currently assigned to that computer. The signature for the bind function is ~~~c int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen); ~~~ Hint: Networking tends to use big-endian numbers. You will need to explicitly convert your IP addresses/ports into network order. You might want to investigate the functions `htons`, `htonl`, and `inet_addr`. ## Listening for a Connection The signature for the listen function is ~~~c int listen(int sockfd, int backlog); ~~~ ## Accepting a Connection The signature for the accept function is ~~~c int accept(int sockfd, struct sockaddr * addr, socklent_t * addrlen); ~~~ ## Initiating a Connection The client initiates a TCP connection using the connect function. The signature for this function is ~~~c int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen); ~~~ ## Reading and Writing to a Socket Given a connected TCP socket file descriptor, you can read and write to the network just the same as you would read and write to a file! In C, the UNIX IO functions are `read` and `write`. For this assignment, however, I am asking you to use `recv` and `send`, which provide a bit more control and flexibility. For one thing, the `recv` command has a way of letting you know when the other side closes the connection. ## Closing a Socket It is good form to close your socket when they are no longer needed. # Submitting Your Assignment You will submit your code and/or responses on gradescope. **Only one partner should submit.** The submitter will add the other partner through the gradescope interface. To pass the autograder (if one exists for this assignment), your output must exactly match the expected output. Your program output should be similar to the example execution above, and the autograder on gradescope will show you the correct output if yours is not formatted properly. You can use [text-compare](https://text-compare.com/) to compare your output to the expected output and that should give you an idea if you have a misspelled word or extra space (or if I do). Additional details for using gradescope can be found here: - [Submitting an Assignment](https://help.gradescope.com/article/ccbpppziu9-student-submit-work) - [Adding Group Members](https://help.gradescope.com/article/m5qz2xsnjy-student-add-group-members) - [gradescope Student Help Center](https://help.gradescope.com/category/cyk4ij2dwi-student-workflow)