Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Homework 10 - Socket Chat

From now on, we’ll assume that you work on homework by connecting to the CS portal and that you are familiar with the command line environment. If you have not been practicing with the terminal, we strongly encourage reviewing Lab 1.

We will also assume that you ran the setup script from that lab and have all modules (including clang and git) by default.

In this assignment, you’ll take the server code we supplied and the client code you wrote in lab 13 and combine them to make a command-line 2-party chat program.

Requirements

Write a single file called schat.c. Use only C library functions and code you wrote in it: no third-party libraries or C++.

schat.c should have a main function that accepts command-line arguments.

  • If given no arguments, it should run in server mode and pick a random ephemeral-range port (as described below)
  • If given one argument, it should run in server mode and use the port number given as the first argument
  • If given two arguments (the first an IP address, the second a port number) it should run in client mode, connecting to that server.

Server start

The server should begin by

  1. Pick a port
    • Pick a random ephemeral-range port, like the lab server code did, if there was no command line argument
    • Use the given port, if there was one command line argument
  2. Display that port number to the terminal, like the lab server code did
  3. Listen for IPv4 connections on any IP address, like the lab server code did
  4. accept only once, unlike the lab server’s accept loop
  5. close the listener socket before working with the accepted socket

Client start

The client should begin by

  1. connecting to the given IP address and port, like your lab client did

Server and Client

Both should then proceed as follows:

  1. Repeatedly (i.e., in an infinite loop) use poll1 to pick either the connected socket (from the server’s accept or the client’s connect) or the standard input stream2 to read3 from. Use a 1-minute4 timeout for poll.
  2. If poll returns a positive number (i.e., it succeeded),
    1. If the standard input has revents including POLLIN, read from standard input and write what you read to the socket.
    2. If the socket has revents including POLLIN, read from the socket and write what you read to standard output5. You may assume no single message is more than 4096 bytes, to avoid needing to loop your read/write calls.

Undefined behaviors

This assignment does not require you to handle the following in any particular way:

  1. Giving notice of server IP address
  2. Failure of any of the socket, read, or write instructions
  3. Handling the closing of the remote connection
  4. Stopping if the poll call times out
  5. Having any way to end the program other than Ctrl+C
  6. Avoiding memory leaks
  7. Clean display when the remote message arrives while the user it typing
  8. Displaying who sent which message

You do need to avoid buffer overflows, use-after-free, and other memory bugs. You are also invited to add sane behaviors for all of the above cases, but are not required to do so.

Example

In a simple implementation, once the client and server connect everything that is typed in one will appear in the other after you press enter.

ServerClient
$ 
$ 

As a reminder, you don’t need to be exactly like the above; the initial display, format of output, and behavior of the server after the client ends are all undefined by this assignment.

Tips

This assignment requires looking things up

You will notice all we said about poll was “check the manual page”. This is by design. We hope you now know enough to learn a bit on your own and use it.

It is also possible to look things up online. Except for online man-pages6, this is a bad idea. In general, online example code is explaining something nuanced within a specific context, and it takes some experience before you are able to tease out the part you can use from the context it is discussed within. I expect if you go to a search engine to find example code, you’ll end up with a lot of code that does not work or meet the required specification in some nuanced way.

Use lldb

When you get a segfault, you should

  1. recompile with clang -g -fsanitize=address schat.c
  2. load in a debugger with lldb a.out
  3. run and see the line of code that segfaulted

This will be far easier than trying to locate the segfault without a debugger or the address sanitizer.

You may also find a debugger useful for other kinds of errors.

Feedback

Gradescope for this assignment will only give coarse-grained feedback; that is, can it send or receive messages with your server or client code. Do not expect detailed or compilation feedback from Gradescope.

Writing your code

For this assignment, we are expecting that you will write your code in a command-line editor (vim, nano, etc) on the portal. If you need to refresh, please review Lab 1.

Using an IDE (such as Visual Studio Code, IntelliJ IDEA, etc, or an online editor or compiler will result in an immediate 0 on the assigment. Sorry to be strict on this, but one of the goals of this course is to gain familiarity with command-line tools.

Why a CLI editor?

It is common to interact with servers that do not have their own monitors. In these cases, you typically attach to the server via ssh and have access only to a terminal, not a full windowing environment. The more comfortable you are with doing common programming tasks in the terminal, the better these experiences will be.

Grading

For this assignment, the grade will consist of an autograded component (for correctness) and a code style grade. The breakdown is as follows:

  • 85% code correctness (passing Gradescope tests)
  • 5% well indented (readable) code
    • You should indent your code as if it were Python; that is, indent whenever you would use curly braces.
  • 5% good variable names
    • Use names that express your code’s meaning.
  • 5% comments
    • Document your code with comments so that you (and we) can better read what you wrote.
    • Write comments that explain any tricky sections as well as tell us (in English) what each section of your code is intended to do.
    • Hint: it might be helpful to write the comments first so that you have a rough sketch of your algorithm before implementation.

Submission

Submit your code to Gradescope.

Do not expect immediate or compilation feedback from an autograder – it will only test whether your client and server functionality works.

Note: the Gradescope submission will not be available until a few days before the deadline, and will then only allow a total of 15 submissions. We encourage you to write your code early and test it before submitting to Gradescope.

  1. see man 3 poll which has some example code in it. There’s also a man 2 poll; you want man 3 poll instead 

  2. which is always already opened as file descriptor 0 

  3. Note: this means you’ll need to use POLLIN as the fds[i].events instead of the POLLOUT | POLLWRBAND used in the manual page example. 

  4. 60 thousand milliseconds 

  5. which is always already opened as file descriptor 1 

  6. And even those vary a lot in how up-to-date they are… 


Copyright © 2023 John Hott, portions Luther Tychonievich.
Released under the CC-BY-NC-SA 4.0 license.
Creative Commons License