Per chi avesse in mente di scrivere un webserver da zero e fosse in cerca di codice da cui partire, ho scritto un webserver davvero minimale (anch'io sono all'inizio ) ma già pienamente funzionante (si limita a stampare un HTML di esempio con scritto "Hello world"). Va avviato come superutente ovviamente. Va da sé che se volete espanderlo dovete studiarvi bene il protocollo HTTP 1.1. Buon lavoro

codice:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>

#define SERVER_PORT 80

void sendString (const int * nSocketId, const char * sContent) {
	int nIdx = 0;
	while (* (sContent + nIdx)) { write(* nSocketId, sContent + nIdx++, 1); }
}

int main () {

	int nReqSize = 1024;
	char *sRequest = malloc(nReqSize);
	socklen_t nAddrLen;
	int nReqSocketId, nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
	struct sockaddr_in oAddress;

	oAddress.sin_family = AF_INET;
	oAddress.sin_addr.s_addr = INADDR_ANY;
	oAddress.sin_port = htons(SERVER_PORT);

	if (nMainSocketId > 0) {
		printf("The socket has been created\n");
	}

	if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress)) == 0) {
		printf("The socket has been opened\nHTTP server listening on port %d\n", SERVER_PORT);
	} else {
		printf("The port %d is busy\n", SERVER_PORT);
		exit(1);
	}

	while (1) {

		if (listen(nMainSocketId, 10) < 0) {
			perror("server: listen");
			exit(1);
		}

		nReqSocketId = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);

		if (nReqSocketId < 0) {
			perror("server: accept");
			exit(1);
		}

		recv(nReqSocketId, sRequest, nReqSize, 0);

		if (nReqSocketId > 0){
			printf("The Client is connected...\n\n%s\n", sRequest);
		}

		sendString(&nReqSocketId, "HTTP/1.1 200 OK\n");
		sendString(&nReqSocketId, "Content-length: 47\n");
		sendString(&nReqSocketId, "Content-Type: text/html\n\n");
		sendString(&nReqSocketId, "<html><body><h1>Hello world</h1></body></html>\n");
		close(nReqSocketId);

	}

	close(nMainSocketId);

	return 0;

}