{"id":7568,"date":"2026-04-03T07:49:32","date_gmt":"2026-04-03T06:49:32","guid":{"rendered":"https:\/\/workboot.fr\/ciela\/?page_id=7568"},"modified":"2026-04-14T15:54:27","modified_gmt":"2026-04-14T14:54:27","slug":"sockets-en-c-ansi","status":"publish","type":"page","link":"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/","title":{"rendered":"Socket TCP en C ansi"},"content":{"rendered":"\n<nav aria-label=\"Table des mati\u00e8res\" class=\"wp-block-table-of-contents\"><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#serveur-tcp\">Serveur TCP<\/a><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#makefile\">Makefile<\/a><\/li><\/ol><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#client-tcp\">Client TCP<\/a><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#makefile-1\">Makefile<\/a><\/li><\/ol><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#muti-serveur-fork\">Muti_serveur (fork)<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#serveur-http\">Serveur http <\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"https:\/\/workboot.fr\/ciela\/sockets-en-c-ansi\/#serveur-http-multi-client\">Serveur http multi-client<\/a><\/li><\/ol><\/nav>\n\n\n\n<pre class=\"wp-block-code\"><code>serveur_fd = socket(AF_INET, SOCK_STREAM, 0)\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>AF_INET : Famille d&rsquo;adresses IPv4<\/li>\n\n\n\n<li>SOCK_STREAM : Type de socket (TCP, fiable, connexion orient\u00e9e flux)<\/li>\n\n\n\n<li>0 : Protocole par d\u00e9faut (TCP pour SOCK_STREAM)<\/li>\n\n\n\n<li>Retour : Descripteur de fichier (entier) ou -1 si erreur<\/li>\n<\/ul>\n\n\n\n<h2 id=\"serveur-tcp\" class=\"wp-block-heading\">Serveur TCP<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;sys\/types.h>\n#include &lt;sys\/socket.h>\n#include &lt;netinet\/in.h>\n#include &lt;arpa\/inet.h>\n#include &lt;netdb.h>\n\n#define PORT 8888\n#define BUFFER_SIZE 1024\n\nint main(int argc, char *argv[]) {\n    int sock_fd;\n    struct sockaddr_in adresse_serveur;\n    struct hostent *serveur;\n    char buffer[BUFFER_SIZE];\n    char message[BUFFER_SIZE];\n    int bytes_recus;\n    struct in_addr **addr_list;  \/* Pour une version plus explicite *\/\n\n    \/* V\u00e9rification des arguments *\/\n    if (argc &lt; 2) {\n        fprintf(stderr, \"Usage: %s &lt;adresse_serveur>\\n\", argv[0]);\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 1. Cr\u00e9ation du socket *\/\n    sock_fd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sock_fd &lt; 0) {\n        perror(\"Erreur cr\u00e9ation socket\");\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 2. R\u00e9solution du nom d'h\u00f4te *\/\n    serveur = gethostbyname(argv[1]);\n    if (serveur == NULL) {\n        fprintf(stderr, \"H\u00f4te inconnu : %s\\n\", argv[1]);\n        close(sock_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 3. Configuration de l'adresse *\/\n    memset(&amp;adresse_serveur, 0, sizeof(adresse_serveur));\n    adresse_serveur.sin_family = AF_INET;\n    \n    \/* M\u00e9thode alternative plus explicite *\/\n    addr_list = (struct in_addr **)serveur->h_addr_list;\n    adresse_serveur.sin_addr = *addr_list[0];\n    adresse_serveur.sin_port = htons(PORT);\n\n    \/* 4. Connexion au serveur *\/\n    if (connect(sock_fd, (struct sockaddr *)&amp;adresse_serveur, sizeof(adresse_serveur)) &lt; 0) {\n        perror(\"Erreur connect\");\n        close(sock_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    printf(\"Connect\u00e9 au serveur %s:%d\\n\", argv[1], PORT);\n    printf(\"Adresse IP : %s\\n\", inet_ntoa(adresse_serveur.sin_addr));\n\n    \/* 5. \u00c9change de donn\u00e9es *\/\n    while (1) {\n        printf(\"Message \u00e0 envoyer (ou 'quit' pour quitter) : \");\n        fgets(message, BUFFER_SIZE, stdin);\n        \n        \/* Suppression du saut de ligne *\/\n        message[strcspn(message, \"\\n\")] = '\\0';\n        \n        if (strcmp(message, \"quit\") == 0) {\n            break;\n        }\n        \n        \/* Envoi *\/\n        send(sock_fd, message, strlen(message), 0);\n        \n        \/* R\u00e9ception de la r\u00e9ponse *\/\n        bytes_recus = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0);\n        if (bytes_recus &lt;= 0) {\n            printf(\"Serveur d\u00e9connect\u00e9\\n\");\n            break;\n        }\n        \n        buffer[bytes_recus] = '\\0';\n        printf(\"R\u00e9ponse du serveur : %s\\n\", buffer);\n    }\n\n    \/* 6. Fermeture *\/\n    close(sock_fd);\n    return 0;\n}<\/pre>\n\n\n\n<h3 id=\"makefile\" class=\"wp-block-heading\">Makefile<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"md\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CC = gcc\nCFLAGS = -Wall -Wextra -ansi -pedantic\n\nall: serveur\n\nserveur: serveur_tcp.c\n\t$(CC) $(CFLAGS) -o serveur serveur_tcp.c\n\nclean:\n\trm -f serveur\n\n.PHONY: all clean\n<\/pre>\n\n\n\n<h2 id=\"client-tcp\" class=\"wp-block-heading\">Client TCP<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;sys\/types.h>\n#include &lt;sys\/socket.h>\n#include &lt;netinet\/in.h>\n#include &lt;arpa\/inet.h>\n#include &lt;netdb.h>\n\n#define PORT 8888\n#define BUFFER_SIZE 1024\n\nint main(int argc, char *argv[]) {\n    int sock_fd;\n    struct sockaddr_in adresse_serveur;\n    struct hostent *serveur;\n    char buffer[BUFFER_SIZE];\n    char message[BUFFER_SIZE];\n    int bytes_recus;\n    struct in_addr **addr_list;  \/* Pour une version plus explicite *\/\n\n    \/* V\u00e9rification des arguments *\/\n    if (argc &lt; 2) {\n        fprintf(stderr, \"Usage: %s &lt;adresse_serveur>\\n\", argv[0]);\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 1. Cr\u00e9ation du socket *\/\n    sock_fd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sock_fd &lt; 0) {\n        perror(\"Erreur cr\u00e9ation socket\");\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 2. R\u00e9solution du nom d'h\u00f4te *\/\n    serveur = gethostbyname(argv[1]);\n    if (serveur == NULL) {\n        fprintf(stderr, \"H\u00f4te inconnu : %s\\n\", argv[1]);\n        close(sock_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    \/* 3. Configuration de l'adresse *\/\n    memset(&amp;adresse_serveur, 0, sizeof(adresse_serveur));\n    adresse_serveur.sin_family = AF_INET;\n    \n    \/* M\u00e9thode alternative plus explicite *\/\n    addr_list = (struct in_addr **)serveur->h_addr_list;\n    adresse_serveur.sin_addr = *addr_list[0];\n    adresse_serveur.sin_port = htons(PORT);\n\n    \/* 4. Connexion au serveur *\/\n    if (connect(sock_fd, (struct sockaddr *)&amp;adresse_serveur, sizeof(adresse_serveur)) &lt; 0) {\n        perror(\"Erreur connect\");\n        close(sock_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    printf(\"Connect\u00e9 au serveur %s:%d\\n\", argv[1], PORT);\n    printf(\"Adresse IP : %s\\n\", inet_ntoa(adresse_serveur.sin_addr));\n\n    \/* 5. \u00c9change de donn\u00e9es *\/\n    while (1) {\n        printf(\"Message \u00e0 envoyer (ou 'quit' pour quitter) : \");\n        fgets(message, BUFFER_SIZE, stdin);\n        \n        \/* Suppression du saut de ligne *\/\n        message[strcspn(message, \"\\n\")] = '\\0';\n        \n        if (strcmp(message, \"quit\") == 0) {\n            break;\n        }\n        \n        \/* Envoi *\/\n        send(sock_fd, message, strlen(message), 0);\n        \n        \/* R\u00e9ception de la r\u00e9ponse *\/\n        bytes_recus = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0);\n        if (bytes_recus &lt;= 0) {\n            printf(\"Serveur d\u00e9connect\u00e9\\n\");\n            break;\n        }\n        \n        buffer[bytes_recus] = '\\0';\n        printf(\"R\u00e9ponse du serveur : %s\\n\", buffer);\n    }\n\n    \/* 6. Fermeture *\/\n    close(sock_fd);\n    return 0;\n}<\/pre>\n\n\n\n<h3 id=\"makefile-1\" class=\"wp-block-heading\">Makefile<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"md\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CC = gcc\nCFLAGS = -Wall -Wextra -ansi -pedantic\n\nall: client\n\nclient: client_tcp.c\n\t$(CC) $(CFLAGS) -o client client_tcp.c\n\nclean:\n\trm -f client\n\n.PHONY: all clean\n<\/pre>\n\n\n\n<h2 id=\"muti-serveur-fork\" class=\"wp-block-heading\">Muti_serveur (fork)<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;sys\/types.h>\n#include &lt;sys\/socket.h>\n#include &lt;sys\/wait.h>\n#include &lt;netinet\/in.h>\n#include &lt;arpa\/inet.h>\n#include &lt;signal.h>\n\n#define PORT 8888\n#define BUFFER_SIZE 1024\n#define MAX_CLIENTS 10\n\n\/* Gestionnaire de signaux pour \u00e9viter les processus zombies *\/\nvoid gestionnaire_sigchld(int signo) {\n    \/* waitpid avec WNOHANG pour ne pas bloquer *\/\n    while (waitpid(-1, NULL, WNOHANG) > 0);\n}\n\n\/* Fonction pour traiter chaque client *\/\nvoid traiter_client(int client_fd, struct sockaddr_in adresse_client) {\n    char buffer[BUFFER_SIZE];\n    int bytes_lus;\n    int i;\n    char client_ip[INET_ADDRSTRLEN];\n    \n    \/* Convertir l'adresse IP en cha\u00eene *\/\n    inet_ntop(AF_INET, &amp;adresse_client.sin_addr, client_ip, INET_ADDRSTRLEN);\n    printf(\"[Processus %d] Client connect\u00e9 : %s:%d\\n\", \n           getpid(), \n           client_ip, \n           ntohs(adresse_client.sin_port));\n    \n    \/* Communication avec le client *\/\n    while ((bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0)) > 0) {\n        buffer[bytes_lus] = '\\0';\n        printf(\"[Processus %d] Re\u00e7u : %s\", getpid(), buffer);\n        \n        \/* Conversion en majuscules *\/\n        for (i = 0; i &lt; bytes_lus; i++) {\n            if (buffer[i] >= 'a' &amp;&amp; buffer[i] &lt;= 'z') {\n                buffer[i] = buffer[i] - 'a' + 'A';\n            }\n        }\n        \n        \/* Envoi de la r\u00e9ponse *\/\n        send(client_fd, buffer, bytes_lus, 0);\n    }\n    \n    if (bytes_lus == 0) {\n        printf(\"[Processus %d] Client d\u00e9connect\u00e9\\n\", getpid());\n    } else {\n        perror(\"[Processus %d] Erreur recv\");\n    }\n    \n    close(client_fd);\n    printf(\"[Processus %d] Connexion ferm\u00e9e, processus termine\\n\", getpid());\n    exit(0);  \/* Le processus fils se termine *\/\n}\n\nint main(void) {\n    int serveur_fd, client_fd;\n    struct sockaddr_in adresse_serveur, adresse_client;\n    socklen_t taille_client = sizeof(adresse_client);\n    struct sigaction sa;\n    int opt = 1;\n    \n    \/* 1. Configuration du gestionnaire de signaux pour \u00e9viter les zombies *\/\n    sa.sa_handler = gestionnaire_sigchld;\n    sigemptyset(&amp;sa.sa_mask);\n    sa.sa_flags = SA_RESTART;  \/* R\u00e9initialiser les appels syst\u00e8me interrompus *\/\n    if (sigaction(SIGCHLD, &amp;sa, NULL) == -1) {\n        perror(\"Erreur sigaction\");\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* 2. Cr\u00e9ation du socket *\/\n    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);\n    if (serveur_fd &lt; 0) {\n        perror(\"Erreur cr\u00e9ation socket\");\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* 3. Option pour r\u00e9utiliser l'adresse (\u00e9vite \"Address already in use\") *\/\n    if (setsockopt(serveur_fd, SOL_SOCKET, SO_REUSEADDR, &amp;opt, sizeof(opt)) &lt; 0) {\n        perror(\"Erreur setsockopt\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* 4. Configuration de l'adresse du serveur *\/\n    memset(&amp;adresse_serveur, 0, sizeof(adresse_serveur));\n    adresse_serveur.sin_family = AF_INET;\n    adresse_serveur.sin_addr.s_addr = INADDR_ANY;\n    adresse_serveur.sin_port = htons(PORT);\n    \n    \/* 5. Attachement du socket *\/\n    if (bind(serveur_fd, (struct sockaddr *)&amp;adresse_serveur, sizeof(adresse_serveur)) &lt; 0) {\n        perror(\"Erreur bind\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* 6. Mise en \u00e9coute *\/\n    if (listen(serveur_fd, MAX_CLIENTS) &lt; 0) {\n        perror(\"Erreur listen\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n    \n    printf(\"Serveur multi-clients d\u00e9marr\u00e9 sur le port %d\\n\", PORT);\n    printf(\"PID du serveur principal : %d\\n\", getpid());\n    printf(\"En attente de connexions...\\n\\n\");\n    \n    \/* 7. Boucle principale d'acceptation *\/\n    while (1) {\n        \/* Accepter une nouvelle connexion *\/\n        client_fd = accept(serveur_fd, (struct sockaddr *)&amp;adresse_client, &amp;taille_client);\n        if (client_fd &lt; 0) {\n            perror(\"Erreur accept\");\n            continue;\n        }\n        \n        \/* Cr\u00e9ation d'un processus fils pour g\u00e9rer le client *\/\n        pid_t pid = fork();\n        \n        if (pid &lt; 0) {\n            perror(\"Erreur fork\");\n            close(client_fd);\n            continue;\n        }\n        \n        if (pid == 0) {\n            \/* Processus fils *\/\n            close(serveur_fd);  \/* Le fils n'a pas besoin du socket d'\u00e9coute *\/\n            traiter_client(client_fd, adresse_client);\n            \/* Ne jamais arriver ici *\/\n        } else {\n            \/* Processus p\u00e8re *\/\n            close(client_fd);   \/* Le p\u00e8re n'a pas besoin du socket client *\/\n            printf(\"[P\u00e8re %d] Nouveau client connect\u00e9, processus fils cr\u00e9\u00e9 : %d\\n\", \n                   getpid(), pid);\n        }\n    }\n    \n    \/* 8. Fermeture (jamais atteint dans cet exemple) *\/\n    close(serveur_fd);\n    return 0;\n}<\/pre>\n\n\n\n<h2 id=\"serveur-http\" class=\"wp-block-heading\">Serveur http <\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* serveur_http_minimal.c - Version simplifi\u00e9e pour tester *\/\n#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;sys\/types.h>\n#include &lt;sys\/socket.h>\n#include &lt;netinet\/in.h>\n#include &lt;arpa\/inet.h>\n\n#define PORT 8080\n#define BUFFER_SIZE 4096\n\nint main(void) {\n    int serveur_fd, client_fd;\n    struct sockaddr_in adresse_serveur, adresse_client;\n    socklen_t taille_client = sizeof(adresse_client);\n    char buffer[BUFFER_SIZE];\n    int bytes_lus;\n    char *reponse_ok = \"HTTP\/1.1 200 OK\\r\\n\"\n                       \"Content-Type: text\/html\\r\\n\"\n                       \"Content-Length: 135\\r\\n\"\n                       \"Connection: close\\r\\n\"\n                       \"\\r\\n\"\n                       \"&lt;!DOCTYPE html>\\n\"\n                       \"&lt;html>\\n\"\n                       \"&lt;head>&lt;title>Test Serveur&lt;\/title>&lt;\/head>\\n\"\n                       \"&lt;body>\\n\"\n                       \"&lt;h1>Bienvenue sur mon serveur HTTP!&lt;\/h1>\\n\"\n                       \"&lt;p>Ceci est une reponse HTML.&lt;\/p>\\n\"\n                       \"&lt;\/body>\\n\"\n                       \"&lt;\/html>\\n\";\n    \n    char *reponse_404 = \"HTTP\/1.1 404 Not Found\\r\\n\"\n                        \"Content-Type: text\/html\\r\\n\"\n                        \"Content-Length: 105\\r\\n\"\n                        \"Connection: close\\r\\n\"\n                        \"\\r\\n\"\n                        \"&lt;!DOCTYPE html>\\n\"\n                        \"&lt;html>\\n\"\n                        \"&lt;body>\\n\"\n                        \"&lt;h1>404 - Page non trouvee&lt;\/h1>\\n\"\n                        \"&lt;\/body>\\n\"\n                        \"&lt;\/html>\\n\";\n\n    \/* Cr\u00e9ation socket *\/\n    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);\n    if (serveur_fd &lt; 0) {\n        perror(\"Erreur cr\u00e9ation socket\");\n        exit(EXIT_FAILURE);\n    }\n\n    \/* Configuration *\/\n    memset(&amp;adresse_serveur, 0, sizeof(adresse_serveur));\n    adresse_serveur.sin_family = AF_INET;\n    adresse_serveur.sin_addr.s_addr = INADDR_ANY;\n    adresse_serveur.sin_port = htons(PORT);\n\n    \/* Bind *\/\n    if (bind(serveur_fd, (struct sockaddr *)&amp;adresse_serveur, sizeof(adresse_serveur)) &lt; 0) {\n        perror(\"Erreur bind\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    \/* Listen *\/\n    if (listen(serveur_fd, 5) &lt; 0) {\n        perror(\"Erreur listen\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    printf(\"Serveur HTTP en \u00e9coute sur le port %d\\n\", PORT);\n\n    while (1) {\n        client_fd = accept(serveur_fd, (struct sockaddr *)&amp;adresse_client, &amp;taille_client);\n        if (client_fd &lt; 0) {\n            perror(\"Erreur accept\");\n            continue;\n        }\n\n        printf(\"Client connect\u00e9 : %s:%d\\n\", \n               inet_ntoa(adresse_client.sin_addr), \n               ntohs(adresse_client.sin_port));\n\n        \/* Lire la requ\u00eate (optionnel, on ignore son contenu) *\/\n        bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);\n        if (bytes_lus > 0) {\n            buffer[bytes_lus] = '\\0';\n            printf(\"Requ\u00eate re\u00e7ue:\\n%s\\n\", buffer);\n            \n            \/* R\u00e9ponse simple *\/\n            if (strstr(buffer, \"GET \/ \") || strstr(buffer, \"GET \/index.html\")) {\n                send(client_fd, reponse_ok, strlen(reponse_ok), 0);\n                printf(\"R\u00e9ponse 200 OK envoy\u00e9e\\n\");\n            } else {\n                send(client_fd, reponse_404, strlen(reponse_404), 0);\n                printf(\"R\u00e9ponse 404 envoy\u00e9e\\n\");\n            }\n        }\n\n        close(client_fd);\n        printf(\"Connexion ferm\u00e9e\\n\\n\");\n    }\n\n    close(serveur_fd);\n    return 0;\n}<\/pre>\n\n\n\n<h2 id=\"serveur-http-multi-client\" class=\"wp-block-heading\">Serveur http multi-client<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;sys\/types.h>\n#include &lt;sys\/socket.h>\n#include &lt;sys\/wait.h>\n#include &lt;netinet\/in.h>\n#include &lt;arpa\/inet.h>\n#include &lt;signal.h>\n#include &lt;time.h>\n\n#define PORT 8080\n#define BUFFER_SIZE 4096\n#define MAX_CLIENTS 100\n\nint clients_actifs = 0;\nint compteur_clients = 0;\n\nvoid gestionnaire_sigchld(int signo) {\n    while (waitpid(-1, NULL, WNOHANG) > 0) {\n        clients_actifs--;\n    }\n}\n\n\/* Envoyer une r\u00e9ponse HTTP *\/\nvoid envoyer_reponse_http(int client_fd, const char *body) {\n    char reponse[BUFFER_SIZE];\n    \n    sprintf(reponse,\n            \"HTTP\/1.1 200 OK\\r\\n\"\n            \"Content-Type: text\/html; charset=UTF-8\\r\\n\"\n            \"Content-Length: %ld\\r\\n\"\n            \"Connection: close\\r\\n\"\n            \"Server: ANSI-C\/1.0\\r\\n\"\n            \"\\r\\n\"\n            \"%s\",\n            strlen(body), body);\n    \n    send(client_fd, reponse, strlen(reponse), 0);\n}\n\n\/* Page d'accueil *\/\nvoid envoyer_accueil(int client_fd, int numero_client) {\n    char body[BUFFER_SIZE];\n    time_t now;\n    char date_str[64];\n    \n    time(&amp;now);\n    strftime(date_str, sizeof(date_str), \"%d\/%m\/%Y %H:%M:%S\", localtime(&amp;now));\n    \n    sprintf(body,\n            \"&lt;html>\\n\"\n            \"&lt;head>\\n\"\n            \"&lt;title>Serveur ANSI C&lt;\/title>\\n\"\n            \"&lt;\/head>\\n\"\n            \"&lt;body>\\n\"\n            \"&lt;h1>Serveur ANSI C&lt;\/h1>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;h2>Client numero : #%d&lt;\/h2>\\n\"\n            \"&lt;p>Clients actifs : %d&lt;\/p>\\n\"\n            \"&lt;p>Total clients servis : %d&lt;\/p>\\n\"\n            \"&lt;p>Date\/Heure : %s&lt;\/p>\\n\"\n            \"&lt;p>Port : %d | PID : %d&lt;\/p>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;p>&lt;a href='\/stats'>Voir les statistiques&lt;\/a>&lt;\/p>\\n\"\n            \"&lt;p>&lt;a href='\/quit'>Quitter&lt;\/a>&lt;\/p>\\n\"\n            \"&lt;\/body>\\n\"\n            \"&lt;\/html>\\n\",\n            numero_client, clients_actifs, compteur_clients, date_str, PORT, getpid());\n    \n    envoyer_reponse_http(client_fd, body);\n}\n\n\/* Page statistiques *\/\nvoid envoyer_stats(int client_fd, int numero_client) {\n    char body[BUFFER_SIZE];\n    \n    sprintf(body,\n            \"&lt;html>\\n\"\n            \"&lt;head>\\n\"\n            \"&lt;title>Statistiques&lt;\/title>\\n\"\n            \"&lt;\/head>\\n\"\n            \"&lt;body>\\n\"\n            \"&lt;h1>Statistiques&lt;\/h1>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;h2>Votre numero : #%d&lt;\/h2>\\n\"\n            \"&lt;p>Clients actuellement connectes : %d&lt;\/p>\\n\"\n            \"&lt;p>Total clients servis depuis demarrage : %d&lt;\/p>\\n\"\n            \"&lt;p>Capacite maximale : %d clients&lt;\/p>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;p>&lt;a href='\/'>Retour accueil&lt;\/a>&lt;\/p>\\n\"\n            \"&lt;\/body>\\n\"\n            \"&lt;\/html>\\n\",\n            numero_client, clients_actifs, compteur_clients, MAX_CLIENTS);\n    \n    envoyer_reponse_http(client_fd, body);\n}\n\n\/* Page 404 *\/\nvoid envoyer_404(int client_fd) {\n    char body[BUFFER_SIZE];\n    \n    sprintf(body,\n            \"&lt;html>\\n\"\n            \"&lt;head>\\n\"\n            \"&lt;title>404&lt;\/title>\\n\"\n            \"&lt;\/head>\\n\"\n            \"&lt;body>\\n\"\n            \"&lt;h1>404 - Page non trouvee&lt;\/h1>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;p>La page demandee n'existe pas.&lt;\/p>\\n\"\n            \"&lt;p>&lt;a href='\/'>Retour accueil&lt;\/a>&lt;\/p>\\n\"\n            \"&lt;\/body>\\n\"\n            \"&lt;\/html>\\n\");\n    \n    envoyer_reponse_http(client_fd, body);\n}\n\n\/* Page au revoir *\/\nvoid envoyer_au_revoir(int client_fd) {\n    char body[BUFFER_SIZE];\n    \n    sprintf(body,\n            \"&lt;html>\\n\"\n            \"&lt;head>\\n\"\n            \"&lt;title>Au revoir&lt;\/title>\\n\"\n            \"&lt;\/head>\\n\"\n            \"&lt;body>\\n\"\n            \"&lt;h1>Au revoir !&lt;\/h1>\\n\"\n            \"&lt;hr>\\n\"\n            \"&lt;p>Merci d'avoir visite notre serveur ANSI C.&lt;\/p>\\n\"\n            \"&lt;p>&lt;a href='\/'>Nouvelle connexion&lt;\/a>&lt;\/p>\\n\"\n            \"&lt;\/body>\\n\"\n            \"&lt;\/html>\\n\");\n    \n    envoyer_reponse_http(client_fd, body);\n}\n\n\/* Extraire le chemin de la requ\u00eate HTTP *\/\nvoid extraire_chemin(const char *requete, char *chemin) {\n    char method[16];\n    char path[256];\n    char version[16];\n    \n    sscanf(requete, \"%s %s %s\", method, path, version);\n    strcpy(chemin, path);\n}\n\nvoid traiter_client(int client_fd, struct sockaddr_in adresse_client, int numero_client) {\n    char buffer[BUFFER_SIZE];\n    int bytes_lus;\n    char chemin[256];\n    char client_ip[INET_ADDRSTRLEN];\n    \n    inet_ntop(AF_INET, &amp;adresse_client.sin_addr, client_ip, INET_ADDRSTRLEN);\n    \n    printf(\"[Client #%d] Connecte depuis %s:%d\\n\", \n           numero_client, client_ip, ntohs(adresse_client.sin_port));\n    \n    \/* Lire la requ\u00eate *\/\n    bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);\n    if (bytes_lus &lt;= 0) {\n        close(client_fd);\n        exit(0);\n    }\n    \n    buffer[bytes_lus] = '\\0';\n    extraire_chemin(buffer, chemin);\n    \n    printf(\"[Client #%d] Chemin: %s\\n\", numero_client, chemin);\n    \n    \/* Router selon le chemin *\/\n    if (strcmp(chemin, \"\/\") == 0 || strcmp(chemin, \"\/index.html\") == 0) {\n        envoyer_accueil(client_fd, numero_client);\n    }\n    else if (strcmp(chemin, \"\/stats\") == 0) {\n        envoyer_stats(client_fd, numero_client);\n    }\n    else if (strcmp(chemin, \"\/quit\") == 0) {\n        envoyer_au_revoir(client_fd);\n    }\n    else {\n        envoyer_404(client_fd);\n    }\n    \n    printf(\"[Client #%d] Deconnexion\\n\", numero_client);\n    close(client_fd);\n    exit(0);\n}\n\nint main(void) {\n    int serveur_fd, client_fd;\n    struct sockaddr_in adresse_serveur, adresse_client;\n    socklen_t taille_client = sizeof(adresse_client);\n    int opt = 1;\n    int numero_nouveau_client;\n    \n    \/* Gestion des signaux *\/\n    signal(SIGCHLD, gestionnaire_sigchld);\n    \n    \/* Cr\u00e9ation socket *\/\n    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);\n    if (serveur_fd &lt; 0) {\n        perror(\"socket\");\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* Option reuse address *\/\n    setsockopt(serveur_fd, SOL_SOCKET, SO_REUSEADDR, &amp;opt, sizeof(opt));\n    \n    \/* Configuration adresse *\/\n    memset(&amp;adresse_serveur, 0, sizeof(adresse_serveur));\n    adresse_serveur.sin_family = AF_INET;\n    adresse_serveur.sin_addr.s_addr = INADDR_ANY;\n    adresse_serveur.sin_port = htons(PORT);\n    \n    \/* Bind *\/\n    if (bind(serveur_fd, (struct sockaddr *)&amp;adresse_serveur, sizeof(adresse_serveur)) &lt; 0) {\n        perror(\"bind\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n    \n    \/* Listen *\/\n    if (listen(serveur_fd, MAX_CLIENTS) &lt; 0) {\n        perror(\"listen\");\n        close(serveur_fd);\n        exit(EXIT_FAILURE);\n    }\n    \n    printf(\"\\n========================================\\n\");\n    printf(\"SERVEUR HTTP ANSI C\\n\");\n    printf(\"========================================\\n\");\n    printf(\"Port: %d\\n\", PORT);\n    printf(\"URL: http:\/\/localhost:%d\/\\n\", PORT);\n    printf(\"PID: %d\\n\", getpid());\n    printf(\"========================================\\n\\n\");\n    \n    \/* Boucle principale *\/\n    while (1) {\n        client_fd = accept(serveur_fd, (struct sockaddr *)&amp;adresse_client, &amp;taille_client);\n        if (client_fd &lt; 0) {\n            perror(\"accept\");\n            continue;\n        }\n        \n        clients_actifs++;\n        compteur_clients++;\n        numero_nouveau_client = compteur_clients;\n        \n        printf(\"[SERVEUR] +++ Client #%d connecte (Actifs: %d) +++\\n\", \n               numero_nouveau_client, clients_actifs);\n        \n        {\n            pid_t pid = fork();\n            \n            if (pid == 0) {\n                \/* Processus fils *\/\n                close(serveur_fd);\n                traiter_client(client_fd, adresse_client, numero_nouveau_client);\n                exit(0);\n            } else if (pid > 0) {\n                \/* Processus p\u00e8re *\/\n                close(client_fd);\n            } else {\n                perror(\"fork\");\n                clients_actifs--;\n                close(client_fd);\n            }\n        }\n    }\n    \n    close(serveur_fd);\n    return 0;\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Serveur TCP Makefile Client TCP Makefile Muti_serveur (fork) Serveur http Serveur http multi-client<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","footnotes":""},"class_list":["post-7568","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"admin","author_link":"https:\/\/workboot.fr\/ciela\/author\/admin\/"},"uagb_comment_info":0,"uagb_excerpt":"Serveur TCP Makefile Client TCP Makefile Muti_serveur (fork) Serveur http Serveur http multi-client","_links":{"self":[{"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/pages\/7568","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/comments?post=7568"}],"version-history":[{"count":16,"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/pages\/7568\/revisions"}],"predecessor-version":[{"id":7710,"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/pages\/7568\/revisions\/7710"}],"wp:attachment":[{"href":"https:\/\/workboot.fr\/ciela\/wp-json\/wp\/v2\/media?parent=7568"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}