Programmation Avancée en C


socket_Unix1_server.c

00001 #include <stdio.h> 
00002 #include <stdlib.h> 
00003 #include <unistd.h>
00004 #define __USE_MISC 1
00005 #include <sys/un.h>
00006 #include <sys/wait.h>
00007 #include <sys/types.h>
00008 #include <sys/socket.h>
00009 #include <string.h>    
00010 #include <arpa/inet.h>
00011 
00012 #define TAILLE_MAX 256
00013 #define TAILLE_FILE 14       // Nombre maximal de connections dans la file d'attente.
00014 
00015 void error(char * msg);      // Cf. ligne /*@\ref{network::socket_TCP_client::error} du listing~\ref{network::socket_TCP_client}@*/.
00016 void traitement(int desc_sock); // Cf listing /*@\ref{network::socket_TCP_server::doit}@*/.
00017 // [...]
00018 #define SERVER_PATH "/tmp/server.socket"  // Chemin de la socket du serveur.
00019 
00020 int main()
00021 {
00022         int desc_ecoute, desc_conn;
00023         struct sockaddr_un adr_svr, adr_client;
00024         socklen_t lon = sizeof(struct sockaddr_un); 
00025 
00026         /*** Création de l'adresse de socket Unix du serveur. ***/
00027         memset(&adr_svr, 0, sizeof(adr_svr));     // Remplissage à 0.
00028 #ifndef __GLIBC__   /* La glibc ne définit pas le champ sun_len */
00029         adr_svr.sun_len    = sizeof(adr_svr);
00030 #endif
00031         adr_svr.sun_family = AF_LOCAL;
00032         strncpy(adr_svr.sun_path, SERVER_PATH, sizeof adr_svr.sun_path - 1); /*@\label{network::socket_Unix1_server::strncpy}@*/
00033         adr_svr.sun_path[sizeof adr_svr.sun_path  - 1] = 0;
00034     
00035         /*** Création d'une socket ***/ 
00036         if ((desc_ecoute = socket(AF_LOCAL,SOCK_STREAM,0)) == -1)
00037                 error("[socket]");
00038 
00039         /*** Attachement de la socket - utilisation de SUN_LEN ***/
00040         if (bind(desc_ecoute, (struct sockaddr *) &adr_svr, SUN_LEN(&adr_svr)))
00041                 error("[bind]");
00042 
00043         /*** On en fait une socket d'écoute. ***/
00044         if (listen(desc_ecoute, TAILLE_FILE))
00045                 error("[listen]");
00046         printf("Serveur: à l'écoute sur %s\n", adr_svr.sun_path);
00047 
00048         /*** Boucle principale pour accept(). ***/
00049         while(1) {
00050                 memset(&adr_client, 0, sizeof(adr_client)); // Remplissage à 0.
00051                 desc_conn = accept(desc_ecoute, (struct sockaddr *) &adr_client,
00052                                    &lon);
00053                 if (desc_conn == -1) {
00054                         perror("[accept]");
00055                         continue;
00056                 }
00057                 /*** Gestion concurrente des connexions acceptées ***/
00058                 int pid = fork();
00059                 if (pid == -1) {
00060                         perror("[fork]");
00061                         close(desc_conn);
00062                         continue;
00063                 }
00064                 if (!pid) {         // Création d'un processus fils.
00065                         close(desc_ecoute);    /* Fermeture de la socket
00066                                                   d'écoute par le fils. */
00067                         traitement(desc_conn); // Traitement de la requête.
00068                         exit(EXIT_SUCCESS); // Sortie du processus fils.
00069                 }
00070                 close(desc_conn);          // Le père ferme la socket de travail.
00071                 while( waitpid( -1, NULL, WNOHANG) > 0);
00072         }
00073         close(desc_ecoute);   // Fermeture de la socket.
00074         return EXIT_SUCCESS;
00075 }
00076 
00077 void traitement(int desc_sock) {
00078         char requete[TAILLE_MAX+1], reponse[TAILLE_MAX] = "Nonnnnnnnnn !";
00079         size_t  answer_size = strlen(reponse)+1;
00080 
00081         ssize_t n = recv(desc_sock, requete, TAILLE_MAX-1, 0); // Réception.
00082         if (n < 0) error("[recv]");
00083         requete[TAILLE_MAX] = '\0'; // Précaution pour l'affichage.
00084         printf(" - Requête reçue: <%s> (%ld octets reçus)\n", requete, (long) n);
00085 
00086         n = send(desc_sock, reponse, answer_size, 0); // Émission de la réponse.
00087         if (n != answer_size ) error("[send]");
00088         printf(" - Réponse émise: <%s> (%ld octets envoyés)\n", reponse, (long) n);
00089 }
00090 
00091 
00092 
00093 void error(char * msg) {
00094         perror(msg);
00095         exit(EXIT_FAILURE);
00096 }