serveur_fd = socket(AF_INET, SOCK_STREAM, 0)
  • AF_INET : Famille d’adresses IPv4
  • SOCK_STREAM : Type de socket (TCP, fiable, connexion orientée flux)
  • 0 : Protocole par défaut (TCP pour SOCK_STREAM)
  • Retour : Descripteur de fichier (entier) ou -1 si erreur

Serveur TCP

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

#define PORT 8888
#define BUFFER_SIZE 1024

int main(int argc, char *argv[]) {
    int sock_fd;
    struct sockaddr_in adresse_serveur;
    struct hostent *serveur;
    char buffer[BUFFER_SIZE];
    char message[BUFFER_SIZE];
    int bytes_recus;
    struct in_addr **addr_list;  /* Pour une version plus explicite */

    /* Vérification des arguments */
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <adresse_serveur>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* 1. Création du socket */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        perror("Erreur création socket");
        exit(EXIT_FAILURE);
    }

    /* 2. Résolution du nom d'hôte */
    serveur = gethostbyname(argv[1]);
    if (serveur == NULL) {
        fprintf(stderr, "Hôte inconnu : %s\n", argv[1]);
        close(sock_fd);
        exit(EXIT_FAILURE);
    }

    /* 3. Configuration de l'adresse */
    memset(&adresse_serveur, 0, sizeof(adresse_serveur));
    adresse_serveur.sin_family = AF_INET;
    
    /* Méthode alternative plus explicite */
    addr_list = (struct in_addr **)serveur->h_addr_list;
    adresse_serveur.sin_addr = *addr_list[0];
    adresse_serveur.sin_port = htons(PORT);

    /* 4. Connexion au serveur */
    if (connect(sock_fd, (struct sockaddr *)&adresse_serveur, sizeof(adresse_serveur)) < 0) {
        perror("Erreur connect");
        close(sock_fd);
        exit(EXIT_FAILURE);
    }

    printf("Connecté au serveur %s:%d\n", argv[1], PORT);
    printf("Adresse IP : %s\n", inet_ntoa(adresse_serveur.sin_addr));

    /* 5. Échange de données */
    while (1) {
        printf("Message à envoyer (ou 'quit' pour quitter) : ");
        fgets(message, BUFFER_SIZE, stdin);
        
        /* Suppression du saut de ligne */
        message[strcspn(message, "\n")] = '\0';
        
        if (strcmp(message, "quit") == 0) {
            break;
        }
        
        /* Envoi */
        send(sock_fd, message, strlen(message), 0);
        
        /* Réception de la réponse */
        bytes_recus = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0);
        if (bytes_recus <= 0) {
            printf("Serveur déconnecté\n");
            break;
        }
        
        buffer[bytes_recus] = '\0';
        printf("Réponse du serveur : %s\n", buffer);
    }

    /* 6. Fermeture */
    close(sock_fd);
    return 0;
}

Makefile

CC = gcc
CFLAGS = -Wall -Wextra -ansi -pedantic

all: serveur

serveur: serveur_tcp.c
	$(CC) $(CFLAGS) -o serveur serveur_tcp.c

clean:
	rm -f serveur

.PHONY: all clean

Client TCP

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

#define PORT 8888
#define BUFFER_SIZE 1024

int main(int argc, char *argv[]) {
    int sock_fd;
    struct sockaddr_in adresse_serveur;
    struct hostent *serveur;
    char buffer[BUFFER_SIZE];
    char message[BUFFER_SIZE];
    int bytes_recus;
    struct in_addr **addr_list;  /* Pour une version plus explicite */

    /* Vérification des arguments */
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <adresse_serveur>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* 1. Création du socket */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        perror("Erreur création socket");
        exit(EXIT_FAILURE);
    }

    /* 2. Résolution du nom d'hôte */
    serveur = gethostbyname(argv[1]);
    if (serveur == NULL) {
        fprintf(stderr, "Hôte inconnu : %s\n", argv[1]);
        close(sock_fd);
        exit(EXIT_FAILURE);
    }

    /* 3. Configuration de l'adresse */
    memset(&adresse_serveur, 0, sizeof(adresse_serveur));
    adresse_serveur.sin_family = AF_INET;
    
    /* Méthode alternative plus explicite */
    addr_list = (struct in_addr **)serveur->h_addr_list;
    adresse_serveur.sin_addr = *addr_list[0];
    adresse_serveur.sin_port = htons(PORT);

    /* 4. Connexion au serveur */
    if (connect(sock_fd, (struct sockaddr *)&adresse_serveur, sizeof(adresse_serveur)) < 0) {
        perror("Erreur connect");
        close(sock_fd);
        exit(EXIT_FAILURE);
    }

    printf("Connecté au serveur %s:%d\n", argv[1], PORT);
    printf("Adresse IP : %s\n", inet_ntoa(adresse_serveur.sin_addr));

    /* 5. Échange de données */
    while (1) {
        printf("Message à envoyer (ou 'quit' pour quitter) : ");
        fgets(message, BUFFER_SIZE, stdin);
        
        /* Suppression du saut de ligne */
        message[strcspn(message, "\n")] = '\0';
        
        if (strcmp(message, "quit") == 0) {
            break;
        }
        
        /* Envoi */
        send(sock_fd, message, strlen(message), 0);
        
        /* Réception de la réponse */
        bytes_recus = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0);
        if (bytes_recus <= 0) {
            printf("Serveur déconnecté\n");
            break;
        }
        
        buffer[bytes_recus] = '\0';
        printf("Réponse du serveur : %s\n", buffer);
    }

    /* 6. Fermeture */
    close(sock_fd);
    return 0;
}

Makefile

CC = gcc
CFLAGS = -Wall -Wextra -ansi -pedantic

all: client

client: client_tcp.c
	$(CC) $(CFLAGS) -o client client_tcp.c

clean:
	rm -f client

.PHONY: all clean

Muti_serveur (fork)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>

#define PORT 8888
#define BUFFER_SIZE 1024
#define MAX_CLIENTS 10

/* Gestionnaire de signaux pour éviter les processus zombies */
void gestionnaire_sigchld(int signo) {
    /* waitpid avec WNOHANG pour ne pas bloquer */
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

/* Fonction pour traiter chaque client */
void traiter_client(int client_fd, struct sockaddr_in adresse_client) {
    char buffer[BUFFER_SIZE];
    int bytes_lus;
    int i;
    char client_ip[INET_ADDRSTRLEN];
    
    /* Convertir l'adresse IP en chaîne */
    inet_ntop(AF_INET, &adresse_client.sin_addr, client_ip, INET_ADDRSTRLEN);
    printf("[Processus %d] Client connecté : %s:%d\n", 
           getpid(), 
           client_ip, 
           ntohs(adresse_client.sin_port));
    
    /* Communication avec le client */
    while ((bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0)) > 0) {
        buffer[bytes_lus] = '\0';
        printf("[Processus %d] Reçu : %s", getpid(), buffer);
        
        /* Conversion en majuscules */
        for (i = 0; i < bytes_lus; i++) {
            if (buffer[i] >= 'a' && buffer[i] <= 'z') {
                buffer[i] = buffer[i] - 'a' + 'A';
            }
        }
        
        /* Envoi de la réponse */
        send(client_fd, buffer, bytes_lus, 0);
    }
    
    if (bytes_lus == 0) {
        printf("[Processus %d] Client déconnecté\n", getpid());
    } else {
        perror("[Processus %d] Erreur recv");
    }
    
    close(client_fd);
    printf("[Processus %d] Connexion fermée, processus termine\n", getpid());
    exit(0);  /* Le processus fils se termine */
}

int main(void) {
    int serveur_fd, client_fd;
    struct sockaddr_in adresse_serveur, adresse_client;
    socklen_t taille_client = sizeof(adresse_client);
    struct sigaction sa;
    int opt = 1;
    
    /* 1. Configuration du gestionnaire de signaux pour éviter les zombies */
    sa.sa_handler = gestionnaire_sigchld;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;  /* Réinitialiser les appels système interrompus */
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("Erreur sigaction");
        exit(EXIT_FAILURE);
    }
    
    /* 2. Création du socket */
    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (serveur_fd < 0) {
        perror("Erreur création socket");
        exit(EXIT_FAILURE);
    }
    
    /* 3. Option pour réutiliser l'adresse (évite "Address already in use") */
    if (setsockopt(serveur_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("Erreur setsockopt");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }
    
    /* 4. Configuration de l'adresse du serveur */
    memset(&adresse_serveur, 0, sizeof(adresse_serveur));
    adresse_serveur.sin_family = AF_INET;
    adresse_serveur.sin_addr.s_addr = INADDR_ANY;
    adresse_serveur.sin_port = htons(PORT);
    
    /* 5. Attachement du socket */
    if (bind(serveur_fd, (struct sockaddr *)&adresse_serveur, sizeof(adresse_serveur)) < 0) {
        perror("Erreur bind");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }
    
    /* 6. Mise en écoute */
    if (listen(serveur_fd, MAX_CLIENTS) < 0) {
        perror("Erreur listen");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("Serveur multi-clients démarré sur le port %d\n", PORT);
    printf("PID du serveur principal : %d\n", getpid());
    printf("En attente de connexions...\n\n");
    
    /* 7. Boucle principale d'acceptation */
    while (1) {
        /* Accepter une nouvelle connexion */
        client_fd = accept(serveur_fd, (struct sockaddr *)&adresse_client, &taille_client);
        if (client_fd < 0) {
            perror("Erreur accept");
            continue;
        }
        
        /* Création d'un processus fils pour gérer le client */
        pid_t pid = fork();
        
        if (pid < 0) {
            perror("Erreur fork");
            close(client_fd);
            continue;
        }
        
        if (pid == 0) {
            /* Processus fils */
            close(serveur_fd);  /* Le fils n'a pas besoin du socket d'écoute */
            traiter_client(client_fd, adresse_client);
            /* Ne jamais arriver ici */
        } else {
            /* Processus père */
            close(client_fd);   /* Le père n'a pas besoin du socket client */
            printf("[Père %d] Nouveau client connecté, processus fils créé : %d\n", 
                   getpid(), pid);
        }
    }
    
    /* 8. Fermeture (jamais atteint dans cet exemple) */
    close(serveur_fd);
    return 0;
}

Serveur http

/* serveur_http_minimal.c - Version simplifiée pour tester */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080
#define BUFFER_SIZE 4096

int main(void) {
    int serveur_fd, client_fd;
    struct sockaddr_in adresse_serveur, adresse_client;
    socklen_t taille_client = sizeof(adresse_client);
    char buffer[BUFFER_SIZE];
    int bytes_lus;
    char *reponse_ok = "HTTP/1.1 200 OK\r\n"
                       "Content-Type: text/html\r\n"
                       "Content-Length: 135\r\n"
                       "Connection: close\r\n"
                       "\r\n"
                       "<!DOCTYPE html>\n"
                       "<html>\n"
                       "<head><title>Test Serveur</title></head>\n"
                       "<body>\n"
                       "<h1>Bienvenue sur mon serveur HTTP!</h1>\n"
                       "<p>Ceci est une reponse HTML.</p>\n"
                       "</body>\n"
                       "</html>\n";
    
    char *reponse_404 = "HTTP/1.1 404 Not Found\r\n"
                        "Content-Type: text/html\r\n"
                        "Content-Length: 105\r\n"
                        "Connection: close\r\n"
                        "\r\n"
                        "<!DOCTYPE html>\n"
                        "<html>\n"
                        "<body>\n"
                        "<h1>404 - Page non trouvee</h1>\n"
                        "</body>\n"
                        "</html>\n";

    /* Création socket */
    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (serveur_fd < 0) {
        perror("Erreur création socket");
        exit(EXIT_FAILURE);
    }

    /* Configuration */
    memset(&adresse_serveur, 0, sizeof(adresse_serveur));
    adresse_serveur.sin_family = AF_INET;
    adresse_serveur.sin_addr.s_addr = INADDR_ANY;
    adresse_serveur.sin_port = htons(PORT);

    /* Bind */
    if (bind(serveur_fd, (struct sockaddr *)&adresse_serveur, sizeof(adresse_serveur)) < 0) {
        perror("Erreur bind");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }

    /* Listen */
    if (listen(serveur_fd, 5) < 0) {
        perror("Erreur listen");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }

    printf("Serveur HTTP en écoute sur le port %d\n", PORT);

    while (1) {
        client_fd = accept(serveur_fd, (struct sockaddr *)&adresse_client, &taille_client);
        if (client_fd < 0) {
            perror("Erreur accept");
            continue;
        }

        printf("Client connecté : %s:%d\n", 
               inet_ntoa(adresse_client.sin_addr), 
               ntohs(adresse_client.sin_port));

        /* Lire la requête (optionnel, on ignore son contenu) */
        bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
        if (bytes_lus > 0) {
            buffer[bytes_lus] = '\0';
            printf("Requête reçue:\n%s\n", buffer);
            
            /* Réponse simple */
            if (strstr(buffer, "GET / ") || strstr(buffer, "GET /index.html")) {
                send(client_fd, reponse_ok, strlen(reponse_ok), 0);
                printf("Réponse 200 OK envoyée\n");
            } else {
                send(client_fd, reponse_404, strlen(reponse_404), 0);
                printf("Réponse 404 envoyée\n");
            }
        }

        close(client_fd);
        printf("Connexion fermée\n\n");
    }

    close(serveur_fd);
    return 0;
}

Serveur http multi-client

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <time.h>

#define PORT 8080
#define BUFFER_SIZE 4096
#define MAX_CLIENTS 100

int clients_actifs = 0;
int compteur_clients = 0;

void gestionnaire_sigchld(int signo) {
    while (waitpid(-1, NULL, WNOHANG) > 0) {
        clients_actifs--;
    }
}

/* Envoyer une réponse HTTP */
void envoyer_reponse_http(int client_fd, const char *body) {
    char reponse[BUFFER_SIZE];
    
    sprintf(reponse,
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/html; charset=UTF-8\r\n"
            "Content-Length: %ld\r\n"
            "Connection: close\r\n"
            "Server: ANSI-C/1.0\r\n"
            "\r\n"
            "%s",
            strlen(body), body);
    
    send(client_fd, reponse, strlen(reponse), 0);
}

/* Page d'accueil */
void envoyer_accueil(int client_fd, int numero_client) {
    char body[BUFFER_SIZE];
    time_t now;
    char date_str[64];
    
    time(&now);
    strftime(date_str, sizeof(date_str), "%d/%m/%Y %H:%M:%S", localtime(&now));
    
    sprintf(body,
            "<html>\n"
            "<head>\n"
            "<title>Serveur ANSI C</title>\n"
            "</head>\n"
            "<body>\n"
            "<h1>Serveur ANSI C</h1>\n"
            "<hr>\n"
            "<h2>Client numero : #%d</h2>\n"
            "<p>Clients actifs : %d</p>\n"
            "<p>Total clients servis : %d</p>\n"
            "<p>Date/Heure : %s</p>\n"
            "<p>Port : %d | PID : %d</p>\n"
            "<hr>\n"
            "<p><a href='/stats'>Voir les statistiques</a></p>\n"
            "<p><a href='/quit'>Quitter</a></p>\n"
            "</body>\n"
            "</html>\n",
            numero_client, clients_actifs, compteur_clients, date_str, PORT, getpid());
    
    envoyer_reponse_http(client_fd, body);
}

/* Page statistiques */
void envoyer_stats(int client_fd, int numero_client) {
    char body[BUFFER_SIZE];
    
    sprintf(body,
            "<html>\n"
            "<head>\n"
            "<title>Statistiques</title>\n"
            "</head>\n"
            "<body>\n"
            "<h1>Statistiques</h1>\n"
            "<hr>\n"
            "<h2>Votre numero : #%d</h2>\n"
            "<p>Clients actuellement connectes : %d</p>\n"
            "<p>Total clients servis depuis demarrage : %d</p>\n"
            "<p>Capacite maximale : %d clients</p>\n"
            "<hr>\n"
            "<p><a href='/'>Retour accueil</a></p>\n"
            "</body>\n"
            "</html>\n",
            numero_client, clients_actifs, compteur_clients, MAX_CLIENTS);
    
    envoyer_reponse_http(client_fd, body);
}

/* Page 404 */
void envoyer_404(int client_fd) {
    char body[BUFFER_SIZE];
    
    sprintf(body,
            "<html>\n"
            "<head>\n"
            "<title>404</title>\n"
            "</head>\n"
            "<body>\n"
            "<h1>404 - Page non trouvee</h1>\n"
            "<hr>\n"
            "<p>La page demandee n'existe pas.</p>\n"
            "<p><a href='/'>Retour accueil</a></p>\n"
            "</body>\n"
            "</html>\n");
    
    envoyer_reponse_http(client_fd, body);
}

/* Page au revoir */
void envoyer_au_revoir(int client_fd) {
    char body[BUFFER_SIZE];
    
    sprintf(body,
            "<html>\n"
            "<head>\n"
            "<title>Au revoir</title>\n"
            "</head>\n"
            "<body>\n"
            "<h1>Au revoir !</h1>\n"
            "<hr>\n"
            "<p>Merci d'avoir visite notre serveur ANSI C.</p>\n"
            "<p><a href='/'>Nouvelle connexion</a></p>\n"
            "</body>\n"
            "</html>\n");
    
    envoyer_reponse_http(client_fd, body);
}

/* Extraire le chemin de la requête HTTP */
void extraire_chemin(const char *requete, char *chemin) {
    char method[16];
    char path[256];
    char version[16];
    
    sscanf(requete, "%s %s %s", method, path, version);
    strcpy(chemin, path);
}

void traiter_client(int client_fd, struct sockaddr_in adresse_client, int numero_client) {
    char buffer[BUFFER_SIZE];
    int bytes_lus;
    char chemin[256];
    char client_ip[INET_ADDRSTRLEN];
    
    inet_ntop(AF_INET, &adresse_client.sin_addr, client_ip, INET_ADDRSTRLEN);
    
    printf("[Client #%d] Connecte depuis %s:%d\n", 
           numero_client, client_ip, ntohs(adresse_client.sin_port));
    
    /* Lire la requête */
    bytes_lus = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
    if (bytes_lus <= 0) {
        close(client_fd);
        exit(0);
    }
    
    buffer[bytes_lus] = '\0';
    extraire_chemin(buffer, chemin);
    
    printf("[Client #%d] Chemin: %s\n", numero_client, chemin);
    
    /* Router selon le chemin */
    if (strcmp(chemin, "/") == 0 || strcmp(chemin, "/index.html") == 0) {
        envoyer_accueil(client_fd, numero_client);
    }
    else if (strcmp(chemin, "/stats") == 0) {
        envoyer_stats(client_fd, numero_client);
    }
    else if (strcmp(chemin, "/quit") == 0) {
        envoyer_au_revoir(client_fd);
    }
    else {
        envoyer_404(client_fd);
    }
    
    printf("[Client #%d] Deconnexion\n", numero_client);
    close(client_fd);
    exit(0);
}

int main(void) {
    int serveur_fd, client_fd;
    struct sockaddr_in adresse_serveur, adresse_client;
    socklen_t taille_client = sizeof(adresse_client);
    int opt = 1;
    int numero_nouveau_client;
    
    /* Gestion des signaux */
    signal(SIGCHLD, gestionnaire_sigchld);
    
    /* Création socket */
    serveur_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (serveur_fd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    
    /* Option reuse address */
    setsockopt(serveur_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    /* Configuration adresse */
    memset(&adresse_serveur, 0, sizeof(adresse_serveur));
    adresse_serveur.sin_family = AF_INET;
    adresse_serveur.sin_addr.s_addr = INADDR_ANY;
    adresse_serveur.sin_port = htons(PORT);
    
    /* Bind */
    if (bind(serveur_fd, (struct sockaddr *)&adresse_serveur, sizeof(adresse_serveur)) < 0) {
        perror("bind");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }
    
    /* Listen */
    if (listen(serveur_fd, MAX_CLIENTS) < 0) {
        perror("listen");
        close(serveur_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("\n========================================\n");
    printf("SERVEUR HTTP ANSI C\n");
    printf("========================================\n");
    printf("Port: %d\n", PORT);
    printf("URL: http://localhost:%d/\n", PORT);
    printf("PID: %d\n", getpid());
    printf("========================================\n\n");
    
    /* Boucle principale */
    while (1) {
        client_fd = accept(serveur_fd, (struct sockaddr *)&adresse_client, &taille_client);
        if (client_fd < 0) {
            perror("accept");
            continue;
        }
        
        clients_actifs++;
        compteur_clients++;
        numero_nouveau_client = compteur_clients;
        
        printf("[SERVEUR] +++ Client #%d connecte (Actifs: %d) +++\n", 
               numero_nouveau_client, clients_actifs);
        
        {
            pid_t pid = fork();
            
            if (pid == 0) {
                /* Processus fils */
                close(serveur_fd);
                traiter_client(client_fd, adresse_client, numero_nouveau_client);
                exit(0);
            } else if (pid > 0) {
                /* Processus père */
                close(client_fd);
            } else {
                perror("fork");
                clients_actifs--;
                close(client_fd);
            }
        }
    }
    
    close(serveur_fd);
    return 0;
}