"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Construire un serveur TCP simple en C

Construire un serveur TCP simple en C

Publié le 2024-11-08
Parcourir:447

Building a Simple TCP Server in C

Dans cet article de blog, nous explorerons comment créer un simple serveur TCP en C capable de servir des fichiers HTML. Nous décomposerons le code, expliquerons son fonctionnement et discuterons des plans futurs pour améliorer ce projet. C'est un excellent exemple de la façon dont vous pouvez « simplement faire les choses » en C sans trop compliquer le processus !

Aperçu du projet

L'objectif de ce projet est d'implémenter un serveur TCP de base qui écoute les connexions client et sert des fichiers HTML sur demande. Le serveur traitera les demandes des clients, lira le fichier HTML spécifié et renverra le contenu au client sous forme de réponse HTTP.

? Poursuivez la conversation sur Twitter(X) : @trish_07

? Dépôt GitHub : Explorez le référentiel de projets du serveur TCP

Structure du projet

Pour organiser notre code, nous allons structurer le projet comme suit :

tcp_server_c/
├── CMakeLists.txt             # Build configuration
├── include/
│   ├── server.h               # Main server header file
│   ├── html_serve.h           # Header for serve_html function
│   ├── request_handler.h      # Header for handle_client function
│   └── socket_utils.h         # Header for socket utility functions
├── src/
│   ├── server.c               # Main server program
│   ├── html_serve.c           # serve_html function
│   ├── request_handler.c      # handle_client function
│   └── socket_utils.c         # Utility functions for socket operations
└── README.md                  # Project documentation

Répartition du code

1. Utilitaires de socket

Tout d'abord, créons un fichier utilitaire pour gérer l'initialisation du socket. Cela garantira que le code de notre serveur principal reste propre et ciblé.

include/socket_utils.h

#ifndef SOCKET_UTILS_H
#define SOCKET_UTILS_H

#include 

int initialize_server(struct sockaddr_in* address);

#endif

src/socket_utils.c

#include "socket_utils.h"
#include 
#include 
#include 
#include 

#define PORT 8080

int initialize_server(struct sockaddr_in* address) {
    int server_fd;
    int opt = 1;

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket failed!");
        return -1;
    }

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) != 0) {
        perror("setsockopt failed");
        close(server_fd);
        return -1;
    }

    address->sin_family = AF_INET;
    address->sin_addr.s_addr = INADDR_ANY;
    address->sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr*)address, sizeof(*address)) 



2. Fonctionnalité de service HTML

Ensuite, nous allons créer une fonction pour servir les fichiers HTML. Cette fonction lira le contenu d'un fichier HTML et le renverra à l'appelant.

include/html_server.h

#ifndef HTML_SERVER_H
#define HTML_SERVER_H

char* serve_html(const char* filename);

#endif

src/html_server.c

#include "html_server.h"
#include 
#include 
#include 

char* serve_html(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        perror("Error opening file");
        return NULL;
    }

    fseek(file, 0, SEEK_END);
    long length = ftell(file);
    fseek(file, 0, SEEK_SET);

    char* buffer = malloc(length   1);
    if (!buffer) {
        perror("Error allocating memory");
        fclose(file);
        return NULL;
    }

    fread(buffer, 1, length, file);
    buffer[length] = '\0'; // Null-terminate the buffer

    fclose(file);
    return buffer;
}

3. Traitement des demandes des clients

Maintenant, implémentons la logique pour gérer les demandes client entrantes.

include/request_handler.h

#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H

#include 

void handle_client(int new_socket);

#endif

src/request_handler.c

#include "request_handler.h"
#include "html_server.h"
#include 
#include 
#include 

#define BUFFER_SIZE 1024

void handle_client(int new_socket) {
    char buffer[BUFFER_SIZE] = { 0 };
    read(new_socket, buffer, BUFFER_SIZE);

    // Serve the HTML file
    char* html_content = serve_html("../html/index.html");
    if (html_content) {
        write(new_socket, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 48);
        write(new_socket, html_content, strlen(html_content));
    } else {
        const char* not_found_response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n

404 Not Found

"; write(new_socket, not_found_response, strlen(not_found_response)); } free(html_content); close(new_socket); // Close the connection with the current client }

4. Logique du serveur principal

Enfin, rassemblons le tout dans le fichier principal.

src/main.c

#include 
#include 
#include 
#include 
#include 
#include "socket_utils.h"
#include "request_handler.h"

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);

    server_fd = initialize_server(&address);
    if (server_fd == -1) {
        return EXIT_FAILURE;
    }

    printf("Server listening on port: 8080\n");

    while (1) {
        if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) 



Projets futurs

À l'avenir, nous prévoyons de mettre en œuvre plusieurs améliorations et fonctionnalités :

  1. Prise en charge multithreading : pour gérer plusieurs connexions client simultanément, nous introduirons des fonctionnalités de threading pour améliorer l'efficacité du serveur.
  2. Servage de contenu dynamique : implémentez des fonctionnalités pour diffuser du contenu dynamique en l'intégrant à un moteur de création de modèles léger.
  3. Journalisation : ajoutez un mécanisme de journalisation pour suivre les requêtes, les erreurs et les performances du serveur.
  4. Fonctionnalités de sécurité : découvrez l'ajout de la prise en charge HTTPS et de la validation des entrées pour améliorer la sécurité.
  5. Gestion améliorée des erreurs : implémentez une meilleure gestion des erreurs pour divers scénarios, tels que fichier introuvable, surcharge du serveur, etc.

Conclusion

Ce simple projet de serveur TCP sert d'exemple fondamental de la façon de créer un serveur Web en C, démontrant la puissance et la simplicité du langage. En nous appuyant sur cette base, nous pouvons développer des fonctionnalités plus sophistiquées et améliorer les performances, ce qui en fait une solution robuste pour diffuser du contenu Web.

Vous pouvez retrouver le code source complet et contribuer au projet sur GitHub : GitHub Repository Link.

N'hésitez pas à nous faire part de vos commentaires, à poser des questions ou à proposer vos idées pour de futures améliorations !


Déclaration de sortie Cet article est reproduit à: https://dev.to/trish_07/building-a-simple-tcp-server-in-c-2h85 S'il y a une contrefaçon, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3