DEV Community

Cover image for Understanding Web Servers by Building One in C
Uthsob Chakraborty
Uthsob Chakraborty

Posted on

1

Understanding Web Servers by Building One in C

Web servers — the magical thing.
Is it really magical? Pretty much, yes. But let’s break down this magic today. For fun, I’ve built a basic one using C and the socket library. You can find the backstory and full code here.

Before diving into code, let’s first understand: what is a web server?


By reading this blog, you're already interacting with a web server — specifically, the one hosting this blog. But how does it actually work?

When you access this page through a browser, communication happens over HTTP (Hypertext Transfer Protocol).
Your browser sends a request to a remote cloud server where the blog is hosted.
The web server receives that request and responds with content — like an index.html or blog.html file.

This process is built on two main protocols:

  • TCP/IP – for establishing connections and transmitting data.
  • HTTP – for structuring the exchange of web content (pages, APIs, etc.).

Process diagram

Sounds pretty simple, right?
But what’s happening under the hood?

Let’s explore this using a real example — a web server built using C. You can find the full code in the repo:
https://github.com/uthsobcb/esspress

Note: This server doesn’t use a real database — it reads from a .txt file as a data source.


Setting Up: Required Libraries

Since we’ll interact with HTTP, sockets, and the network layer, we need to include the following C standard libraries:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
Enter fullscreen mode Exit fullscreen mode

1. Preparing the Response

The server serves an HTML file (index.html) as the homepage. First, we open the file, read its content, and attach it to a basic HTTP 200 response header.

FILE* html_data;
html_data = fopen("index.html", "r");

char response_data[1024];
fgets(response_data, 1024, html_data);

char http_header[2048] = "HTTP/1.1 200 OK\r\n\n";
strcat(http_header, response_data);
Enter fullscreen mode Exit fullscreen mode

This builds a minimal HTTP response like:

HTTP/1.1 200 OK

<html>...</html>
Enter fullscreen mode Exit fullscreen mode

2. Setting Up the Server

In this part, we define the server socket, specify the IP and port, and bind it to the machine:

int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
server_address.sin_addr.s_addr = INADDR_ANY;
Enter fullscreen mode Exit fullscreen mode

Then bind the socket and start listening for connections:

bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
listen(server_socket, 5);
Enter fullscreen mode Exit fullscreen mode

Look closely at this line:

server_address.sin_port = htons(8001);
Enter fullscreen mode Exit fullscreen mode

We're serving the web on port 8001.


3. Receiving Requests and Sending Responses

Inside an infinite loop, the server accepts incoming client connections and responds based on the requested path.

For example, if the browser sends a request for /, we return the HTML page:

if (strncmp(request_buffer, "GET / ", 6) == 0) {
    send(client_socket, http_header, strlen(http_header), 0);
}
Enter fullscreen mode Exit fullscreen mode

Similarly, when the client requests the /data path, we read data from a db.txt file and send it as plain text:

else if (strncmp(request_buffer, "GET /data", 9) == 0) {
    FILE* db_file = fopen("assets/db.txt", "r");
    ...
    send(client_socket, data_response, strlen(data_response), 0);
}
Enter fullscreen mode Exit fullscreen mode

And if the path is unknown, we send a standard 404 response.


Final Thoughts

This isn’t a production-ready server — it’s a learning project. But it does give you a crystal-clear understanding of how a browser talks to a server, how requests are handled, and how responses are structured.

If you've made it this far, congrats — you now understand the core mechanism behind every website you’ve ever visited.

Feel free to clone, run, and even improve the project:
https://github.com/uthsobcb/esspress

AWS Q Developer image

Build your favorite retro game with Amazon Q Developer CLI in the Challenge & win a T-shirt!

Feeling nostalgic? Build Games Challenge is your chance to recreate your favorite retro arcade style game using Amazon Q Developer’s agentic coding experience in the command line interface, Q Developer CLI.

Participate Now

Top comments (1)

Collapse
 
eliushhimel profile image
Hm Elius Hossain Himel

That's a pretty good explanation.