2025-02-04 HTTP server from scratch in CΒΆ

After getting C sockets working yesterday I decided to create an HTTP server, here is the code:

/*
 *
 * serv_socket.c -- This file acts as a server for my socket connections.
 */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>

#define PORT 9089
#define BUFFER_SIZE 1024

int main() {

  int server_socket;

  struct sockaddr_in serv_in;

  server_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (server_socket == -1) {
    perror("Error [-1] creating socket");
    return 1;
  }

  serv_in.sin_family = AF_INET;
  serv_in.sin_port = htons(PORT);
  serv_in.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(server_socket, (struct sockaddr *)&serv_in, sizeof(serv_in)) < 0) {
    perror("Error binding socket");
    close(server_socket);
    return 1;
  }
  printf("Server listening on port %d\n", PORT);

  if (listen(server_socket, 1) < 0) {
    perror("Error listening on socket");
    close(server_socket);
    return 1;
  }


  int client_socket;
  char client_response[255];

  while (1) {
    client_socket = accept(server_socket, NULL, NULL);
    if (client_socket < 0) {
      perror("Accept failed");
      continue;
    }

    ssize_t recv_size = recv(client_socket, client_response, sizeof(client_response) - 1, 0);
    if (recv_size > 0) {
      client_response[recv_size] = '\0';
    }

    printf("Received request:\n%s\n", client_response);

    char *method = strtok(client_response, " ");
    char *path = strtok(NULL, " ");

    if (method && strcmp(method, "GET") == 0) {

      char *file_path = path + 1;
      if (strcmp(file_path, "") == 0) {
        file_path = "index.html";
      }

      int file = open(file_path, O_RDONLY);
      ssize_t bytes_read;
      char file_buffer[BUFFER_SIZE] = {0};
      char http_response[BUFFER_SIZE] = {0};

      if (file < 0) {
        perror("Error opening file");
        char *not_found_response =
          "HTTP/1.1 404 Not Found\r\n"
          "Content-Type: text/plain\r\n"
          "Content-Length: 15\r\n"
          "Connection: close\r\n"
          "\r\n"
          "404 Not Found";

        send(client_socket, not_found_response, strlen(not_found_response), 0);
      } else {

        snprintf(http_response, sizeof(http_response),
                 "HTTP/1.1 200 OK\r\n"
                 "Content-Type: text/html\r\n"
                 "Connection: close\r\n"
                 "\r\n");

        send(client_socket, http_response, strlen(http_response), 0);
      }
      while ((bytes_read = read(file, file_buffer, sizeof(file_buffer))) > 0) {
        send(client_socket, file_buffer, bytes_read, 0);
      }
      if (bytes_read < 0) {
        perror("Error reading file");
      }
      close(file);
    }

    close(client_socket);
  }


  close(server_socket);
  return 0;
}