Maison > développement back-end > C++ > le corps du texte

Construire un serveur TCP simple en C

DDD
Libérer: 2024-11-04 07:16:01
original
747 Les gens l'ont consulté

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
Copier après la connexion

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 <arpa/inet.h>

int initialize_server(struct sockaddr_in* address);

#endif
Copier après la connexion

src/socket_utils.c

#include "socket_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#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)) < 0) {
        perror("Bind failed!");
        close(server_fd);
        return -1;
    }

    if (listen(server_fd, 3) < 0) {
        perror("Listen failed!");
        close(server_fd);
        return -1;
    }

    return server_fd;
}
Copier après la connexion

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
Copier après la connexion

src/html_server.c

#include "html_server.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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] = '<pre class="brush:php;toolbar:false">#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H

#include <sys/socket.h>

void handle_client(int new_socket);

#endif
Copier après la connexion
'; // 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

#include "request_handler.h"
#include "html_server.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#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<h1>404 Not Found</h1>";
        write(new_socket, not_found_response, strlen(not_found_response));
    }

    free(html_content);
    close(new_socket); // Close the connection with the current client
}
Copier après la connexion

src/request_handler.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#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)) < 0) {
            perror("Connection not accepted!");
            continue;
        }
        handle_client(new_socket); // Handle the client request
    }

    close(server_fd);
    return 0;
}
Copier après la connexion

4. Logique du serveur principal

Enfin, rassemblons le tout dans le fichier principal.

src/main.c

Projets futurs

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

  1. Prise en charge multi-threading : pour gérer plusieurs connexions client simultanément, nous introduirons des fonctionnalités de threading pour améliorer l'efficacité du serveur.
  2. Dynamic Content Serving : 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 des erreurs améliorée : implémentez une meilleure gestion des erreurs pour divers scénarios, tels qu'un fichier introuvable, une surcharge du serveur, etc.

Conclusion

Ce simple projet de serveur TCP sert d'exemple fondamental sur 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 à apporter vos idées pour de futures améliorations !


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!