Lab5: Socket programming
The goal of lab5 is to let you experience some hands-on socket programming by implementing two networking applications: a string concat application and a chat application. You will use socket programming in C.
Section 0: Getting started
- Click the GitHub lab5 link on Canvas homepage to create your lab5 clone on GitHub.
- Start your VM and open the VM’s terminal.
- Clone the lab5 repo to your VM:
$ cd ~ $ git clone git@github.com:NEU-CS3650-labs/lab5-<Your-GitHub-Username>.git lab5
Note that the repo address
git@github.com:...
can be obtained by going to GitHub repo page (your cloned lab5), clicking the green “Code” button, then choosing “SSH”. - Check contents:
$ cd ~/lab5; ls * // you should see: slack.txt chat: Makefile chat_client.c chat_server.c util.c concat: Makefile concat_client.c concat_server.c util.c
- Build the concat server:
$ cd ~/lab5/concat; make $ ./concat_server // you should see: Usage: concat_server server_port [random_seed]
- Build the chat server:
$ cd ~/lab5/chat; make $ ./chat_server // you should see: Usage: chat_server server_port
Section 1: Understanding C socket programming
Socket programming.
In this lab, you will use the following socket interfaces:
function signature | description |
int socket(int domain, int type, int protocol); | socket() creates an endpoint for communication and returns a descriptor. |
ssize_t send(int socket, const void *buffer, size_t length, int flags); | send a message from a socket |
ssize_t recv(int socket, void *buffer, size_t length, int flags); | receive a message from a socket |
int bind(int socket, const struct sockaddr *address, socklen_t address_len); | bind() assigns a name to an unnamed socket. |
int listen(int socket, int backlog); | listen for connections on a socket |
int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); | accept a connection on a socket |
int connect(int socket, const struct sockaddr *address, socklen_t address_len); | initiate a connection on a socket |
To read more details about these functions, use $ man <func name>
.
Multiplexing IOs.
To monitor multiple socket connections, people use select()
to examine a set of I/O file descriptors. The file descriptors are grouped into file descriptor sets (fd_set
). In particular, select()
monitors three sets—readfds
, writefds
, and errorfds
—to see if some of their descriptors are ready for reading, are ready for writing, or have an exceptional condition pending, respectively. Here is the function signature of select()
:
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout);
Here is how to manipulate fd_set
:
function | description |
FD_ZERO(fd_set *set) | Clear all entries from the set. |
FD_SET(int fd, fd_set *set) | Add fd to the set. |
FD_CLR(int fd, fd_set *set) | Remove fd from the set. |
FD_ISSET(int fd, fd_set *set) | Return true if fd is in the set. |
Tutorials: Beej’s Guide to Network Programming
Here are several chapters that are useful for the lab:
- Ch2: What is a socket?
- Ch5.2: socket() - Get the File Descriptor!
- Ch5.3: bind() - What port am I on?
- Ch5.4: connect() - Hey, you!
- Ch5.5: listen() - Will somebody please call me?
- Ch5.6: accept() - “Thank you for calling port 3490.”
- Ch5.7: send() and recv() - Talk to me, baby!
- Ch7.3: select() - Synchronous I/O Multiplexing, Old School
Examples from CS3650 lectures
- sending “hello world” to another machine (Panel 2 and 3)
- code snippet of a chat server using select (Panel 2)
Section 2: a string concat app
Next, you will implement a string concat application. The application has one server (concat_server
) and one client (concat_client
). The server listens and accepts connections from the client. The client sends some string data to the server; the server concatenates another piece of data to that data and sends it back to the client. Finally, the client prints the concatenated data.
Exercise 1 implement concat_server.c
and concat_client.c
- update (04/11) There is a bug in our skeleton code (see this post). There are two ways to fix. Pick one.
$ cd ~/lab5/
and run
$ curl https://naizhengtan.github.io/24spring/labtutorials/lab5.patch | git apply
- OR, open file
concat/util.c
and edit line27
to bestr_buf[len] = '\0';
- Go to the folder of the concat app:
$ cd ~/lab5/concat
- Read instructions in
concat_client.c
and implementTODO
s.- Read instructions in
concat_server.c
and implementTODO
s.- Now, test your implementation:
$ cd ~/lab5/concat; make $ ./concat_server 3650 // the sever should wait for clients // on another terminal $ cd ~/lab5/concat $ ./concat_client 3650 // you should see: =<nCutvqjpranCutvqjpra>= =<SUbQcIoDpRSUbQcIoDpR>= =<MnuxGjytkLMnuxGjytkL>= =<T_^OiZVY`NT_^OiZVY`N>= =<yrrqJlPOoWyrrqJlPOoW>= =<`CKlQRlPL]`CKlQRlPL]>= =<k_CODkxY[^k_CODkxY[^>= =<wjWobpaqUWwjWobpaqUW>= =<^KiiMyAy`\^KiiMyAy`\>= =<\aQnpTpECQ\aQnpTpECQ>=
- Notes: pay attention to possible errors; pay attention tailing
\0
for strings.
Section 3: a chat app
In this exercise, you will implement a simple chat application with a server and two clients:
A (client) <---> S (server) <---> B (client)
In this example, clients A
and B
want to talk. They both connect to the server S
. S
establishes connections with both A
and B
, then takes data coming in from A
and sends them to B
and vice versa. The double-headed arrow indicates that communication can happen in both directions. (This arrangement can also be thought of as S
acting as a proxy server, a common service in networking.)
In addition to forwarding data, S
could also be used to inspect the traffic between A
and B
to ensure it doesn’t contain anything malicious. In our lab, your S
should detect any bad words in the strings being transmitted and replace them with corresponding good words. The bad words are: ["virus", "worm", "malware"]
and their corresponding good words are: ["groot", "hulk", "ironman"]
. Note that the length of the bad word and its corresponding good word is the same. This means after the replaces the bad words with the good words, the length of the string being transmitted does not change.
Exercise 2 implement chat_server.c
and chat_client.c
- Go to the folder of the chat app:
$ cd ~/lab5/chat
- Read instructions in
chat_client.c
and implementTODO
s.- Read instructions in
chat_server.c
and implementTODO
s.- Now, test your implementation:
$ cd ~/lab5/chat; make $ ./chat_server 3650 // the sever should wait for clients // on another terminal, terminal I $ cd ~/lab5/chat $ ./chat_client 3650 // the client should wait for inputs // on yet another terminal, terminal II $ cd ~/lab5/chat $ ./chat_client 3650 // then, type in hello, malware // on terminal I, you should see: hello, ironman
Finally, submit your lab5
Submitting consists of three steps:
- Executing this checklist:
- Fill in
~/lab5/slack.txt
with (1) your name, (2) your NUID, (3) slack hours you used, and (4) acknowledgements. - Make sure that your code builds with no warnings.
note: we will apply a 10% penalty to the compilation warnings you have. - Make sure you have added (
git add
) all files that you created (if any).
- Fill in
Push your code to GitHub:
$ cd ~/lab5 $ git commit -am 'submit lab5' $ git push origin Counting objects: ... .... To ssh://github.com/NEU-CS3650-labs/lab5-<username>.git 7337116..ceed758 main -> main
- Actually submit your lab via Gradescope:
- Navigate to https://www.gradescope.com/ and click on log in.
- Select login with “School Credentials” and select “Northeastern University”.
- Enter Northeastern SSO login information and you should be able to log in to your gradescope account.
- Now, on Canvas, go to the CS3650 course and click on “Gradescope 1.3” from the left navigation bar. You will then be asked to accept the course invitation after which you can access the course on Gradescope.
- On Gradescope, select the lab/assignment you wish to submit and click on “Upload Submission”.
- You will then be asked to upload a zip file consisting of the files that the lab/assignment specifies.
Note: you can either zip all the files within your lab folder, or zip your lab folder; its name must start with “lab5-“ (this is supposed to be your GitHub repo name,lab5-<username>
). If you zip a folder named, for example, “mysubmit”, then Gradescope will complain about it and your submission might not work. - After uploading the zip file, the autograder will evaluate your submission and provide a score for it.
- After the manual grading process is performed by the TAs, your final score for the lab/assignment will be released.
This completes lab5.
Acknowledgments
A python version of this lab is created by Anirudh Sivaraman. CS3650 staff ports the lab to C.