MAT 201B -- Media Networks and Services
Homework Assignment #3b

Introduction

In this assignment you will use UNIX sockets to implement a simple WWW client and WWW server that communicate using a restricted subset of http. The main objective of the assignment is to give you some hands-on experience with sockets.

You should write two programs, a server program (process) and a client program (process); the programs should be compiled separately, so that they each have their own executable image. The two processes will communicate with each other in a connection-oriented manner using sockets.

The client process should first connect() to the server process (after creating the socket, of course). The client should then issue a simple GET http command. This is done by writing the C-string:

    "GET file-name HTTP/1.0\n"
into the client-to-server connection, where file-name is the name of the .html file to be retrieved. This command is then followed by a second string that contains only the newline "\n" string. For example, if the client sends the two strings:
     "GET /index.html HTTP/1.0\n"
     "\n"
to the http server, the http server will respond with the file /index.html. Your client process should write out all of the data returned by the server (see below).

The server process should accept() an incoming connection request. It should then look for the GET request and pick out the file name. Note that a GET request from a real WWW client may have several lines of optional information following the GET. These optional lines, though, will be terminated by a blank line (i.e., a line containing zero or more spaces, terminated by a '\n' (newline) character. Your server should first print out the received GET command as well as any optional lines following the GET (and preceeding the empty line). The server should then respond with the line:

    "HTTP/1.0 200 Document follows\n"
followed by a blank line (i.e., i.e, a string with only blanks, terminated by a '\n'). The server should then send the contents of the requested document, and then close the socket created by the accept() and wait to accept a new connection request. If the document is not found, the server should respond with
     "HTTP/1.0 404 Not Found"
as would a real http server (don't forget the \n).

Additional Notes:

  1. The RFC that defines the http protocol is avialable to you, However, you do not need to print it (or even read it) for this assignment. Note that the RFC is 150 pages long!

  2. We would strongly suggest that everyone begin by writing a client, and getting that client to work with server imj.ucsb.edu. Then write a sequential server and test it with a WWW browser.

  3. In writing your code, make sure to check for an error return from all system calls. (For this assignment, you do not need to check return values for printf or exit however.) If there is an error, the system declared global variable, errno, will give you information about the type of error that occurred, as shown in the example above.

  4. For the socket-related system calls(eg.fork() ), see man pages on the system, you may try xman command.

  5. Note that read and write might return without having read or written the full number of bytes requested. In such a case, these calls will return a positive return value indicating the number of bytes actually read or written. If the number does not correspond with the number requested, be sure to loop back until all the data has been transferred.

  6. Your processes should communicate using the reliable stream protocol (SOCK_STREAM) and the Internet domain protocols (AF_INET). If you need to know your host's IP address, you can telnet to your own machine and seeing the dotted decimal address displayed by the telnet program. You can also use the UNIX nslookup command or you can take a look at the "hosts" file in the /etc directory.

  7. Most of you will be running both the client and server on the same machine (e.g., by starting up the client and running it in the background, and then starting the server [or vice versa). Recall the use of the ampersand to start a process in the background. If you need to kill your server after you have started it, you can use the UNIX kill command. Use the UNIX ps command to find the process id of your server.

  8. Make sure you close every socket that you use in your program. If you abort your program, the socket may still hang around and the next time you try and bind a new socket to the port ID you previously used (but never closed), you may get an error. Also, please be aware that port ID's, when bound to sockets, are system-wide values and thus other students may be using the port number you are trying to use.

    If your server is designed only to terminate upon receipt of a control-C from the keyboard or of a kill signal, then you will want to use the signal system call to make sure all sockets are closed before your server terminates. (A call to exit will insure that these sockets are closed gracefully before the server terminates.) note that the signal system can be used to call a function that you designate to be executed as soon as a control-C or a kill signal is received. In the code fragment below, the user-supplied function cleanExit() will be called when a control-C or kill signal are received. The two calls to signal in the main routine let the OS know that cleanExit should be called on a control-C or a kill signal:

    
      #include <signal.h>
      ........
      main() {
      ........
      signal(SIGTERM,cleanExit);
      signal(SIGINT,cleanExit);
      .......
      }  /* end of main */
    
      void cleanExit()  /* called on control-C or kill */
      {
      /* exit below will close open sockets*/
      exit();      /* all done, so die     */
      }

    For more info on UNIX Signals, checkout the page: UNIX singals .

Testing your client and server

You can test your client and server as follows

What to Turn in

When you turn in your assignment, you should include:

Assignment Grading