Project 1: Simple HTTP Client and Server

 

Due Date: Thursday, Oct 5, 2006, 11:59pm

 

Part I: The HTTP Client

 

I.1. Program Description:

 

You will write a simple HTTP client that does the following: (1) constructs an HTTP1.1 request message based on the user¡¯s command line input, (2) prints the constructed request message on the standard output, (3) sends the constructed request message to the HTTP server specified in the user¡¯s command line input, and (4) receives and writes the response message to an output file.

 

I.2. What You Need to Do:

Command line usage: client [¨Ch] <URL>

 

You will write a program called client.c, client.cc, or client.cpp. The input and output descriptions of the program are as follows.

 

Client program¡¯s input: The client program takes one option ¡®-h¡¯ and one required argument ¡®URL¡¯. The argument ¡®URL¡¯ specifies the URL of the object that the client is requesting from the server. The URL format is

http://hostname:port/file_path. The option identifies the method to be used in the constructed HTTP1.1 request message.

 

Client program¡¯s output: The client program writes the request message constructed locally to the standard output and writes the response message received from the HTTP server to an output file named response.out.

 

You are required to implement the following routines in the client program:

 

1. parse_URL (char *url, char *hostname, int *port, char *identifier): this routine takes the command line argument ¡®URL¡¯ as an input and parses it into the hostname, the port number, and the identifier (the local path of the requested resource). For example, if the URL is http://www.cs.iastate.edu:1234/index.html, then the hostname is www.cs.iastate.edu, the port number is 1234, and the identifier is /index.html.

 

2. int open_conn (char *hostname, int port): this routine takes the hostname and the port number resulting from the routine parse_URL (¡­) as the inputs. This routine opens a socket and connects it to the HTTP server hostname. The output of this routine is the local socket id to be used when sending/receiving HTTP request/response messages.

 

3. char *do_ReqMsg (char *hostname, char *identifier, char *option): this routine takes the hostname, the identifier, and the option specified in the command line as the inputs. Then, it constructs an HTTP1.1 request message based on the option command line argument. Note that the hostname and the identifier are the outputs of the routine parse_URL (...). The request message constructed by your program should be in the form of a string, in which all lines of the message are concatenated.

 

If the option ¡°-h¡± is not specified, construct an HTTP1.1 request message with the ¡®GET¡¯ method. For example, the command line

client http://www.cs.iastate.edu:1234/index.html will result in the HTTP1.1 request message as follows:

 

GET /index.html HTTP/1.1\r\n

Host:www.cs.iastate.edu\r\n

\r\n

 

If the option ¡°-h¡± is specified, construct an HTTP1.1 request message with the ¡®HEAD¡¯ method. For example, the command line

client ¨Ch http://www.cs.iastate.edu:1234/index.html will result in the HTTP1.1 request message as follows:

 

HEAD /index.html HTTP/1.1\r\n

Host:www.cs.iastate.edu\r\n

\r\n

 

4.      print_ReqMsg (char *ReqMsg): the routine writes the constructed HTTP1.1 request message to the standard output. You should make sure that every line, including the last blank line, of the constructed request message is printed onto the standard output.

 

5.      do_comm (int sockfd, char *ReqMsg): this routine takes the sockfd resulting from the routine open_conn(¡­) and the requested message constructed by the routine do_ReqMsg(¡­) as the inputs. The routine then sends the constructed request message, receives the response message, and writes the response message to an output file named response.out.

 

I.3 Compiling the Client Program and Creating the Executable File

 

Use gcc ¨Co client client.c to compile the client program and create the executable file. The executable file is named client.

 

I.4 Testing Your Client Program

 

You can use the client to connect to any HTTP server using port number 80. You should try different URLs and options to make sure that the client works correctly.

   

After your client program terminates, you can create a .html file containing the message body of the response message you have received from the Web server and use any Web browser to read the html file you just created and compare the result with when you directly specify the URL in your Web browser. (Recall that the response message is required to be written to the file named response.out.)

 

I.5 Grading Guideline

 

Total Score: 100 points

 

1. Program Correctness ¨C 80 points

 

2.  Program Robustness ¨C 10 points

¡ìpan style='font:7.0pt "Times New Roman"'>     Properly handling errors in socket operations

¡ìpan style='font:7.0pt "Times New Roman"'>     Properly handling other errors, for example, your program should not continue if the number of arguments specified in the command line is not correct or non-recognized options are specified.

 

3.      Program Components and Comments ¨C 10 points

¡ìspan>    Your client program is named client.c, client.cc, or client.cpp as instructed

¡ìspan>    Your client program consists of all the required routines.

¡ìspan>    Your codes are commented and documented properly.

 

Part II: The HTTP Server

 

II.1. Program Description:

 

You will write a simple HTTP server that is capable of handling one service request at a time. Your HTTP server receives and responds to the service request sent from the simple HTTP client you did in part I. The server program (1) waits for a connection request. If there is a connection request, the server program (2) accepts the connection request, (3) writes the address of the connecting client onto the standard output, (4) reads from the socket the HTTP request message, (5) writes the received HTTP request message and the address of the connecting client to a log file, and (6) responds to the HTTP request message accordingly. After finish serving this connecting client, the server program (7) goes back and waits for a future connection request.

 

II.2. What You Need to Do:

You will implement one program called server.c, server.cc, or server.cpp. The input and output descriptions of the program are as follows.

 

Server program¡¯s input: The server program does not take any input from the user.

 

Server program¡¯s output: The server program (i) reports the address of the connecting client on the standard output and (ii) writes to a log file named server.log the address of the connecting client, the METHOD specified in the received HTTP request message, and the name of the requested object.

 

You are required to implement the following routines in the server program.

 

1. int main ( ): this is the regular main function in C/C++ programming. In this function, the server program opens the socket, binds the socket to a local protocol address, and waits for a connection request from a client. If there is an incoming connection request, the server program accepts the connection, print the address of the client to stdout; reads from the socket the HTTP request message, print to the log file server.log, construct the HTTP response message, and sends the HTTP response message back to the client.

Note: Use your last four digits of your SSN as the port number the server is listening to. This is to avoid any contention for the same port number on the same machine such as popeye.cs.iastate.edu.

 

2.   print_Log (struct sockaddr_in cliaddr, char *ReqMsg): This routine prints the address of the connecting client and the HTTP request message to the log file named server.log. The format of the log file is as follow.

 

Connection from: <client IP address>, Port: <client port number>

Method: <Head/Get>

Object: <the absolute path of the object>

 

Note: In this routine, you may need to use the functions inet_ntop() and ntohs() to convert the network IP address/Port formats to the corresponding host formats.

 

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

  const char *inet_ntop(int family,

const void *addrptr,

char *strptr,

socklen_t len);

 

#include <netinet/in.h>

uint16_t ntohs(uint16_t net16bitvalue);

 

Example

int listenfd, connfd;

struct sockaddr_in cliaddr;

char buff[MAXLINE];

socklen_t len;

 

listenfd = socket();

 

¡­

 

connfd = accept(listenfd, (const struct sockaddr *) &cliaddr, &len);

 

printf(¡°Connection from: %s, Port: %d\n¡±,

inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port));

 

3.      char *do_ResMsg(char *ReqMsg): This routine constructs an HTTP response message according to the HTTP request message read from the socket.

 

a.       The client submits a GET request message.

If the requested object (file) is not found in the directory path specified in the request message, the response message contains the status line ¡°HTTP/1.1 404 Not Found¡± and an empty body. If the requested object is found in the directory path specified in the request message, the response message contains the status line ¡°HTTP/1.1 200 OK¡±, the Content-Length: header line, and the requested object (file) is included in the message body. Please be sure to insert one empty line between the status line and the response message body.

 

b.      The client submits a HEAD request message.

If the requested object (file) is not found in the directory path specified in the request message, the response message contains the status line ¡°HTTP/1.1 404 Not Found¡± and an empty body. If the requested object is found in the directory path specified in the request message, the response message contains the status line ¡°HTTP/1.1 200 OK¡±, and the Last-Modified: header line.

 

Hint: Use the stat() function to obtain the time the file is last modified and the size in bytes of the file.

 

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h> 

int stat(const char *filename, struct stat *buf);

 

II.3. Compiling the Server Program and Creating the Executable File

 

Use gcc ¨Co server server.c to compile the server program and create the executable file. (The executable file is named server.)

 

II.4. Testing Your Server Program

 

¡ìpan style='font:7.0pt "Times New Roman"'>     Use your HTTP client program to test your HTTP server.

 

¡ìpan style='font:7.0pt "Times New Roman"'>     Put an HTML file named testfile.html in the directory of the machine you will run your server program.

 

¡ìpan style='font:7.0pt "Times New Roman"'>     Start your HTTP server by invoking your server program.

 

$ server <enter>

 

{Your server program should be running and wait for a connection request}

 

¡ìpan style='font:7.0pt "Times New Roman"'>     Start your HTTP client by invoking your client program. Assume the server program has been invoked on Popeye.

 

$ client http://popeye.cs.iastate.edu:1234/testfile.html

 

¡ìspan>    Verify the file your client program has received from your HTTP server.

II.5. Grading Guideline

 

Total Score: 100 points

 

1.      Program Correctness ¨C 80 points

 

2.      Program Robustness ¨C 10 points

¡ìspan>    Properly handling errors in socket operations

 

3.         Program Components and Comments ¨C 10 points

¡ìspan>    Your server program is named server.c, server.cc, or server.cpp as instructed

¡ìspan>    Your server program consists of all the required routines.

¡ìspan>    Your codes are commented and documented properly.

 

Submitting Your Project

 

¡ìspan>   Follow the instructions specified in the Turnin Instructions page to submit your project electronically.

¡ìpan style='font:7.0pt "Times New Roman"'>     Use ¡®project1¡¯ as the second argument to submit your project.

¡ìpan style='font:7.0pt "Times New Roman"'>     Please submit only the source files.