Lab 6: Network Servers
This lab focuses primarily on the functionality for setting up and operating
a server. Section
4.8 of the
book illustrates much of this functionality. In addition to general I/O functions
(such as close()
, read()
, and write()
),
you should consult the
C documentation
as needed for the following functions:
-
accept()
,bind()
,inet_ntoa()
,listen()
,setsockopt()
Preliminaries
Set up a bare repository on stu.cs.jmu.edu based on the instructions
in the CS 361 Submission Procedures,
using the name lab6-www.git
.
Implementation requirements: Set up a minimal HTTP server
Most of the work will involve modifying utils.c
to implement a
number of helper functions:
- Complete the code in
build_address()
to set up an IPv4 address within astruct sockaddr_in
. - Using the textbook examples as a reference, set
up a server socket in
setup_server()
. This function should go from making the call tosocket()
until the call tolisten()
. Return the socket file descriptor (or -1 if an error occurs). - Complete
get_connection()
so that it accepts incoming requests and prints the IP address of a connection. Use"Received incoming request from %s\n"
for the format string for printing the address. Return the file descriptor for the connection. - Complete
build_response()
so that it opens the file, usesbuile_response_header()
to build the header, then concatenates the contents. If the file doesn't exist, returnNULL
.
Next, complete the implementation of serve_web()
in
server.c
. The provided code uses the functions in
utils.c
to set up the server socket and get the connection.
You will need to complete the code to read the request, call
build_response()
to get the HTTP response, then write the
response back to the client. If build_response()
returns
NULL
, then write the 404 message indicated. Finally,
close both the server and connection sockets and shut them down.
- You are dealing with TWO socket file descriptors, not one. Once
you pass a file descriptor to
listen()
(i.e., the one that you got fromsocket()
), it becomes a server socket and can only be used for accepting incoming requests (i.e., calls toaccept()
). You cannot pass this file descriptor toread()
orwrite()
. Those functions require the connection file descriptor, which you get as a return value from the call toaccept()
. - After writing the response, you must close and shutdown both file descriptors. If you don't, you'll fail the integration tests. What happens is the first test opens and binds the server socket to the port number. Then, when the next test tries to bind again, it fails because Linux thinks the port number is still in use.