11.4 Using the Server

If we were planning to distribute this program in source form, maintain it on an ongoing basis, or port it to other platforms, we probably would want to package it using GNU Automake and GNU Autoconf, or a similar configuration automation system. Such tools are outside the scope of this book; for more information about them, consult GNU Autoconf, Automake, and Libtool (by Vaughan, Elliston, Tromey, and Taylor, published by New Riders, 2000).

11.4.1 The Makefile

Instead of using Autoconf or a similar tool, we provide a simple Makefile compatible with GNU Make [4] so that it's easy to compile and link the server and its modules. The Makefile is shown in Listing 11.10. See the info page for GNU Make for details of the file's syntax.

[4] GNU Make comes installed on GNU/Linux systems.

Listing 11.10 (Makefile) GNU Make Configuration File for Server Example
### Configuration.  #################################################### 
 
# Default C compiler options. 
CFLAGS                 = -Wall -g 
# C source files for the server. 
SOURCES                = server.c module.c common.c main.c 
# Corresponding object files. 
OBJECTS                = $(SOURCES:.c=.o) 
# Server module shared library files. 
MODULES                = diskfree.so issue.so processes.so time.so 
 
### Rules.  ############################################################ 
 
# Phony targets don't correspond to files that are built; they're names 
# for conceptual build targets. 
.PHONY:         all clean 
 
# Default target: build everything. 
all:            server $(MODULES) 
 
# Clean up build products. 
clean: 
        rm -f $(OBJECTS) $(MODULES) server 
 
# The main server program.  Link with -Wl, -export-dyanamic so 
# dynamically loaded modules can bind symbols in the program.  Link in 
# libdl, which contains calls for dynamic loading. 
server:         $(OBJECTS) 
        $(CC) $(CFLAGS) -Wl,-export-dynamic -o $@ $^ -ldl 
 
# All object files in the server depend on server.h.  But use the 
# default rule for building object files from source files. 
$(OBJECTS):     server.h 
 
# Rule for building module shared libraries from the corresponding 
# source files.  Compile -fPIC and generate a shared object file. 
$(MODULES): \ 
%.so:           %.c server.h 
        $(CC) $(CFLAGS) -fPIC -shared -o $@ $< 

The Makefile provides these targets:

·         all (the default if you invoke make without arguments because it's the first target in the Makefile) includes the server executable and all the modules. The modules are listed in the variable MODULES.

·         clean deletes any build products that are produced by the Makefile.

·         server links the server executable. The source files listed in the variable SOURCES are compiled and linked in.

·         The last rule is a generic pattern for compiling shared object files for server modules from the corresponding source files.

Note that source files for server modules are compiled with the -fPIC option because they are linked into shared libraries (see Section 2.3.2, "Shared Libraries," in Chapter 2).

Also observe that the server executable is linked with the -Wl, -export-dynamic compiler option. With this option, GCC passes the -export-dynamic option to the linker, which creates an executable file that also exports its external symbols as a shared library. This allows modules, which are dynamically loaded as shared libraries, to reference functions from common.c that are linked statically into the server executable.

11.4.2 Building the Server

Building the program is easy. From the directory containing the sources, simply invoke make:

 
% make 
cc -Wall -g   -c -o server.o server.c 
cc -Wall -g   -c -o module.o module.c 
cc -Wall -g   -c -o common.o common.c 
cc -Wall -g   -c -o main.o main.c 
cc -Wall -g -Wl, -export-dynamic -o server server.o module.o common.o main.o -ldl 
cc -Wall -g -fPIC -shared -o diskfree.so diskfree.c 
cc -Wall -g -fPIC -shared -o issue.so issue.c 
cc -Wall -g -fPIC -shared -o processes.so processes.c 
cc -Wall -g -fPIC -shared -o time.so time.c 

This builds the server program and the server module shared libraries.

 
% ls -l server *.so 
-rwxr-xr-x    1 samuel   samuel      25769 Mar 11 01:15 diskfree.so 
-rwxr-xr-x    1 samuel   samuel      31184 Mar 11 01:15 issue.so 
-rwxr-xr-x    1 samuel   samuel      41579 Mar 11 01:15 processes.so 
-rwxr-xr-x    1 samuel   samuel      71758 Mar 11 01:15 server 
-rwxr-xr-x    1 samuel   samuel      13980 Mar 11 01:15 time.so 

11.4.3 Running the Server

To run the server, simply invoke the server executable.

If you do not specify the server port number with the --port (-p) option, Linux will choose one for you; in this case, specify --verbose (-v) to make the server print out the port number in use.

If you do not specify an address with --address (-a), the server runs on all your computer's network addresses. If your computer is attached to a network, that means that others will be capable of accessing the server, provided that they know the correct port number to use and page to request. For security reasons, it's a good idea to specify the localhost address until you're confident that the server works correctly and is not releasing any information that you prefer to not make public. Binding to the localhost causes the server to bind to the local network device (designated "lo")— only programs running on the same computer can connect to it. If you specify a different address, it must be an address that corresponds to your computer:

 
% ./server --address localhost --port 4000 

The server is now running. Open a browser window, and attempt to contact the server at this port number. Request a page whose name matches one of the modules. For instance, to invoke the diskfree.so module, use this URL:

http://localhost:4000/diskfree

Instead of 4000, enter the port number you specified (or the port number that Linux chose for you). Press Ctrl+C to kill the server when you're done.

If you didn't specify localhost as the server address, you can also connect to the server with a Web browser running on another computer by using your computer's hostname in the URL—for example:

http://host.domain.com:4000/diskfree

If you specify the --verbose (-v) option, the server prints some information at startup and displays the numerical Internet address of each client that connects to it. If you connect via the localhost address, the client address will always be 127.0.0.1.

If you experiment with writing your own server modules, you may place them in a different directory than the one containing the server module. In this case, specify that directory with the --module-dir (-m) option. The server will look in this directory for server modules instead.

If you forget the syntax of the command-line options, invoke server with the --help (-h) option.

 
% ./server --help 
Usage: ./server [ options ] 
  -a, --address ADDR        Bind to local address (by default, bind 
                              to all local addresses). 
  -h, --help                Print this information. 
  -m, --module-dir DIR      Load modules from specified directory 
                             (by default, use executable directory). 
  -p, --port PORT           Bind to specified port. 
  -v, --verbose             Print verbose messages.