Lab 13: Chat Client

Due by the end of class

Introduction

In the first few minutes after the Big Bang, the only way to communicate using a computer was a bulletin board system (BBS), a computer that other computers could connect to (usually over a phone line with a modem) and exchange information. Once the material forming the Earth had collected and began to cool, Internet relay chat (IRC) became a popular way for human beings to send messages to each other over the nascent Internet. It was (and is) organized around chat rooms, though private communication is possible. Then, in the dark days when the Babylonians ruled the world, AOL introduced software called AOL Instant Messenger (AIM). Mirabilis had created the ICQ instant messaging (IM) software a year earlier, but AIM quickly became the most popular IM client in North America. The following decade saw the rise of countless IM platforms. Now, the propagation of smart phones and social media sites has made IM largely obsolete. Nevertheless, you, with your C programming skills in hand, are going to write a command-line based IM client using sockets.

Lab Exercise

This client is not a fully featured IM program that keeps a buddy list or allows multiple connections or has a GUI. This implementation is as simple as possible. To make it work, you'll need two terminal screens. Run the server (which will print incoming messages) on one screen. Run the client (which allows you to send outgoing messages) on the other.

The server is provided for you in this file. It goes through a process very similar to the one we discussed in class for servers in general.

  1. Creating a socket
  2. Binding the socket to a port and IP address
  3. Listening for a connection
  4. Accepting a connection
  5. Reading data from the client socket repeatedly
  6. Closing the sockets

Make sure the server is running before you start your client running. The port number you choose must be larger than 1024 but smaller than 65535.

Client

The client is the code you have to write. Your makefile should compile it into an executable called client. Put a line in your makefile to compile server.c into an executable called server as well. We'll break down the process of writing the client into a few steps.

Includes

Use the following #include statements so that you have headers for all the networking functions and structures you might need. You may need to include additional headers for input, output, string manipulation, and other tasks that you are well familiar with.

#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>

Set up

To make a socket connection to a waiting server, you'll need to know the port number and IP address of the server. Read the IP address as a string, assuming the user will type it in as four numbers between 0 and 255 separated by dots (e.g. 74.125.235.101). Read the port number as an unsigned int. Finally, read the user name that will be prepended to all outgoing messages as a string. You can assume that the user name has no spaces in it and that it is no longer than 20 characters.

Making the connection

First, you'll need to create a socket using the socket() function as described in the lecture. Next, you'll need to fill out a sockaddr_in structure with the correct port and IP address specified by the user. Recall that you'll need the htons() function to set the correct endianness of the port. You'll also need the inet_pton() function to convert the user-readable IP address string to the representation that needs to be stored inside the sockaddr_in structure.

Once you have the socket and the structure ready, call the connect() function to connect to the server.

The chat session

During the chat session, you will print out the user name followed by a colon and then read a line of input. For a normal message, copy the user name followed by a colon and the message into a buffer. Feel free to use functions from string.h to do so. Then send the buffer to the server using the write() function. This process of reading from the user and sending data should continue repeatedly.

If the user enters quit, then send only that to the server without prepending the user name. Then, the server will know that the connection is ending. On a quit message, the client should also terminate its loop after sending the message to the server. Finally, it should close its socket.

You cannot use scanf() to read in a line of data since scanf() input is separated by whitespace. Instead, you'll need a function that reads in a line of data into a buffer. Although you should be able to write such a thing in your sleep, it is provided below.

void readLine(char line[])
{	
	int c = 0;	
	int i = 0;

	while( (c = getchar()) != '\n' )
	{
		line[i] = c;
		i++;
	}

	line[i] = '\0';
}

A minor issue: The last thing you read in with scanf() will probably be the user name. Because scanf() is whitespace delimited, it will read up to but not including the newline that sits after the user name. Consequently, the first time you call readLine(), it will give back the empty string. Calling getchar() once before starting the messaging loop will get rid of the extra newline.

Sample Output

Client Output

Your client output should look similar to the following, assuming that you're connecting on port 50002. User input is marked in green.

Enter IP: 127.0.0.1
Enter port: 50002
Enter user name: Julio

*Chat Started*

Julio: P is the funk is the funk is the funk is the funk.
Julio: When the mic is in my hand, I'm never hesitant.  My favorite jam back in the day was Eric B for President.
Julio: Flop mode is the squid.
Julio: quit

*Chat Ended*

For testing purposes, you should start by connecting to the loopback address 127.0.0.1 and chatting with yourself. Once you and a classmate both think your code is working, you should be able to chat with each other. You'll need to agree on port numbers (each client-server pair has to have the same port, but the two pairs don't have to match). You'll also need to know each other's IP addresses.

To find out what your IP address is, use the ifconfig command. (I know it's only a single character different from the Windows command ipconfig, but that's Linux for you.) Its output should include a block of data marked by eth0 on the left (for your first Ethernet connection). The second line of that data should include an IP address marked inet addr:. That's your IP address, at least on the local network.

Server Output

The expected server output for the previous sample execution of the client is below. The only piece of user input, the port number, is marked in green. If the server output isn't right, you need to look closely at the data you're sending it from the client.

Enter port: 50002

*Chat Started*

Julio: P is the funk is the funk is the funk is the funk.
Julio: When the mic is in my hand, I'm never hesitant.  My favorite jam back in the day was Eric B for President.
Julio: Flop mode is the squid.

*Chat Ended*

Turn In

Zip the contents of your lab directory, including the makefile and the source C files. Upload this zip file to Brightspace. Do not include any object files or executables. Running the make command must compile the required C source code file and generate executables named client and server. Typically, this would be done by having an all: target at the top of the makefile, whose dependencies are client and server.

All work must be done individually. Never look at someone else's code. Please refer to the course policies if you have any questions about academic integrity. If you have trouble with the assignment, I am always available for assistance.