/*****************************/ /* serveurUDP_corrige_Q3.1.c */ /*****************************/ #include #include #include #include #include #include #include #include #include #include #include "initCommunication.h" #include "client-serveur.h" // // Constantes de fonctionnement du programme // // #define NB_MAX_REPONSES 10 // Nombre maximum de reponses que le serveur fait // a un client (avant de lui repondre REPONSE_KO) #define NB_THREADS_DANS_POOL 1000 // Nombre de threads dans le pool // Structure permettant de passer un entier en parametre lors // d'un pthread_create union IntPtr { int entier; void *ptr; }; // Mutex evitant les race conditions sur rangClient pthread_mutex_t mutex; void gestionRequete(int fdPointDAcces, struct sockaddr_storage addrEmetteur, socklen_t addrEmetteur_len, message_t requete) { static int rangClient = 0; message_t reponse; // On determine l'emetteur du message char host[NI_MAXHOST], service[NI_MAXSERV]; int rc = getnameinfo((struct sockaddr *) &addrEmetteur, addrEmetteur_len, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV); if (rc != 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "getnameinfo"); // On traite la requete if (requete.infoSup.nbReponsesAuClient == 0) { // C'est un nouveau client if (pthread_mutex_lock(&mutex) != 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "pthread_mutex_lock"); rangClient++; printf("%6d-ieme client a traiter (%s:%s)\n", rangClient, host, service); if (pthread_mutex_unlock(&mutex) != 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "pthread_mutex_unlock"); } if (requete.infoSup.nbReponsesAuClient < NB_MAX_REPONSES) { reponse.typ = REQUETE_OK; CALCUL_PAYLOAD(reponse.infoSup.payload, requete.infoSup.nbReponsesAuClient+1); //usleep(100000); } else { reponse.typ = REQUETE_KO; } ssize_t nbWrite = sendto(fdPointDAcces, &reponse, sizeof(reponse), 0, (struct sockaddr *) &addrEmetteur, addrEmetteur_len); if (nbWrite != sizeof(reponse)) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "sendto"); } void *gestionPointDAcces(void *arg) { union IntPtr ip; ip.ptr = arg; int fdPointDAcces = ip.entier; do { // Attente message struct sockaddr_storage addrEmetteur; socklen_t addrEmetteur_len = sizeof(addrEmetteur); message_t requete; ssize_t nbRead = recvfrom(fdPointDAcces, &requete, sizeof(requete), 0, (struct sockaddr *) &addrEmetteur, &addrEmetteur_len); if (nbRead != sizeof(requete)) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "recvfrom"); // Gestion de cette requete gestionRequete(fdPointDAcces, addrEmetteur, addrEmetteur_len, requete); } while (1); } int main() { int fdPointDAcces = creationPointDAcces(); int i; // Initialisation du mutex pthread_mutex_init(&mutex, NULL); // Creation du pool de threads for (i = 0 ; i < NB_THREADS_DANS_POOL-1 ; i++) { pthread_t thread; union IntPtr ip; ip.entier = fdPointDAcces; int rc = pthread_create(&thread, NULL, gestionPointDAcces, ip.ptr); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_create"); rc = pthread_detach(thread); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_detach"); } // Le thread du main est aussi un thread du pool union IntPtr ip; ip.entier = fdPointDAcces; gestionPointDAcces(ip.ptr); return EXIT_SUCCESS; }