From nmon for Linux

Site: NwebWebserver

nweb Tiny Webserver Example

nweb Tiny Safe Webserver
nweb is a 200 lines of C code example of how a webserver actually works at its core.
It is a static page only server (no fancy live content) and only certain files types.
It actually, works too and a few 100 people use it on the Internet for for their own projects.
Note: This code is a simple sample code and NOT under any license. Use it any way you like.

nweb - A Tiny Safe Web Server with source code!

Have you ever:

  1. Wondered how a web server actually works via a simple example?
  2. Wanted to run a tiny safe web server (but were worried about using a fully blown web server may cause security issues)?
  3. Wondered how to write a program that accepts incoming messages via a network socket?
  4. Just wanted your own web server to experiment, extend and learn with.

Well, look no further – nweb is what you need. This is a simple web server to understand (200 lines of C source code) and you have the source code to look, so you know exactly what it can and can’t do. Add to this the fact it runs just as a regular user (if you use high port numbers), it can not run any server side scripts or programs, so it can’t open up any special privileges or security holes.

nweb only transmits to the browser the following types of files

If your favourite static file type is not in this list, you can simply add it in the source code and recompile to allow it - a few seconds work

The file supplied includes the UNIX source code in C and a precompiled AIX and Linux on Intel versions. The source will compile with the IBM VisualAge C compiler or the GNU C compiler and should run unchanged on AIX, Linux or any other UNIX version for which you care to compile it. On UNIX (assuming the compiler is in your path) just type: cc –O3 nweb.c –o nweb

Summary of the functions within nweb

There are only four functions in the source code and these are explained below:

Pseudo code of the program

Below is the pseudo code for the ~200 lines of source code. It should help you to understand the flow of the program.

output an error message

transmit a fake web page to report a problem

web()  - this function returned the request back to the browser
read from the socket the request
check it’s a simple GET command
check no parent directory requested to escape the web servers home directory
if no file name given assume index.html
check the file extension is valid and supported
check the file is readable by opening it
transmit the HTTP header to the browser
transmit the file contents to the browser
if LINUX sleep for one second to ensure the data arrives at the browser

check the arguments supplied are valid
check the directory supplied is sensible and not a security risk
create a socket, bind it to a port number and start a listening on it
become a daemon process
ignore child programs (to avoid zombies on their death)
forever {
			wait and accept incoming socket connection
			fork a child process
			if the child process
			then call the web function
			else close socket 

System Calls

As you may not have come across some of these system calls before, these are explained in more detail below and in particular how they all fit together. Although, you can always look them up in the manual or on the web, it is hard to see what they do and why they make up a web server, just the source code and manual.

The socket(), bind(), listen() and accept() network system calls, all work together to create a server process. Combined they set up a socket ready for use to communicate over a network. A socket is:

The socket() function creates the socket and returns the file descriptor which can be used with any function that uses file descriptors like read, write, close. The arguments tell the operating system what type of socket and communication you need. There are dozens of permutations and combinations. The arguments used in the program are very typical for a regular general purpose socket using IP and other options are rare in the writer’s experience.

The bind() function attaches a particular port number to the socket. When I client is trying to contact your server is will use the IP address (often found by using a DNS service to convert a hostname to an IP address) and the port number. The port number tells which service you want on the server. The details on most UNIX machines are listed in the /etc/services files. Included in here will be standard port numbers for services like FTP, telnet and web servers (usually port 80 or 8080). You should check the port numbers in this /etc/services file to make sure you don’t try one which is already in use. Although, if you try you should get an error message as it is normally impossible for two servers to use the same port number

The listen() function call tells the operating system you are now ready to accept incoming requests. This is the final switch that makes the socket available to local and remote programs.

The accept(0 function actually stops you program until there is a socket connection request to this IP address and port number. Once the accept function call returns it means that the socket file descriptor is live. If you read bytes from the socket you get characters from the client and it you write bytes to the socket they get tramsmitted to the client. But it is not normal to read or write. Normally, you want to allow multiple clients to access your servers service and if this process does a read or write operation it could block until there are characters to be read or the written characters can be transmitted. This server process should be running the accept function again to allow a new connection to start. The way to handle this is for the server process to start a child process that does the “talking” to the client and any work it needs done and for the main server process to close the socket and rerun the accept function an so await the next client connection. Note: when the child process is started it inherits the parents open sockets and so the child keeps the socket alive.

So it is normal in network servers for you to find code that looks like this (in pseudo code form):

forever {
	Start a child to handle the work

If you set a Korn shell variable like this $ export ABC=123 Then the getenv(“ABC”) function would return a pointer to a null terminated string containing “123”.

These are the regular C library functions but they are used for the reading of the sockets and files sent to the client web browsers as files and sockets are access by the file descriptor. Note: the socket is “opened” with the accept() function – the open() in the code is for opening the requested file.

The nweb.c code only shows you the server side of the socket. For the record here is the code that is required for the client side. Fortunately, the client side is much simpler are you only need to supply the IP address and the port number to make the connection to the server. In the below the servers IP address is and the server port is 8181.

	int sockfd;
	static struct sockaddr_in serv_addr;

	if((sockfd = socket(AF_INET, SOCK_STREAM,0)) <0)
		pexit("Network socket system call");

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(“”);
	serv_addr.sin_port = htons(8181);

	if(connect(connectfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) <0)
		pexit("Network connect system call");

	/* now the sockfd can be used to communicate to the server */

Warning: the bind() and connect() functions take a structure as the argument that must be zero filled before the setting particular options. In the nweb.c the structure is made a static C variable to ensure a it is zero filled when the program is started. If this structure was on the stack as a variable within the function or in the heap of the process it could be filled with old data and so its content not be zero filled. In which case you need to ensure it is zero filled using – the bzero() function can be used to do this.

Example use on nweb:

$ mkdir /home/nag/webpages
$ cd /home/nag/webpages
$ cp /tmp/nweb.tar .
$ tar xvf nweb.tar
$ ls

$ cat sample_index.html
nweb test
This is a test page.
<H1>Header level 1</H1>
<H2>Header level 2</H2>
<LI>This is an unordered list.
<LI>Which means bullet points.
This is a sample gif image
<IMG SRC=”nweb.gif”>
<B>The End</B>

$ cp sample_index.html index.html
$ chmod ugo+x nweb 
$ chmod ugo+r *.html nweb.gif
$ nweb 8181 /home/nag/webpages &
$ hostname

Start your browser and access the website:


Download FileComments
nweb25.cCurrent version 25 - 24th July 2016
Added SIGCHLD support for operating systems that don't support SIGCLD
nweb24.cVersion 24 - 23rd July 2016
nweb24_extra.zipCurrent version 24 client.c and a miniature example of a website for testing purposes only
nweb24_Ubuntu_RaspberryPi3_ARMVersion 24 compiled for Raspberry Pi 3 ARM running Ubuntu 16.04
nweb_AIX6_POWERVersion 24 compiled for AIX 6 (or above) on POWER
Retrieved from
Page last modified on July 24, 2016, at 07:30 PM