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 !
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.
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
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
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; }
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 <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
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 }
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; }
Enfin, rassemblons le tout dans le fichier principal.
src/main.c
À l'avenir, nous prévoyons de mettre en œuvre plusieurs améliorations et fonctionnalités :
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!