#include #include #include #include #include #include #include #include #include #include #include #include "client-serveur.h" static int rangClient = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *traiterConnexion(void *arg){ message_t *pmsg = (message_t *)arg; message_t reponse, requete; FILE *f; char nomTube[TAILLE_POINT_ACCES]; char mEtMme[TAILLE_M_ET_MME]; int fdW, fdR; int nbWrite; int rc = pthread_detach(pthread_self()); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_detach"); rc = pthread_mutex_lock(&mutex); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_mutex_lock"); rangClient++; printf("%6d-ieme client a traiter (point d'access client = %s)\n", rangClient, pmsg->infoSup.pointAcces); /* On vérifie qu'on peut ouvrir le fichier pour les requêtes ultérieures. */ f = fopen("mEtMme.txt", "r"); if (f == NULL) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "pas pu ouvrir mEtMme.txt"); /* On ouvre le tube nommé sur lequel le client pourra venir nous faire */ /* les demandes ultérieures. */ sprintf(nomTube, "%s.%d", NOM_POINT_ACCES_SERV,rangClient); rc = pthread_mutex_unlock(&mutex); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_mutex_unlock"); if (mkfifo(nomTube, S_IRUSR|S_IWUSR) < 0) { if (errno != EEXIST) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "mkfifo pour requetes client-->serveur"); else error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "Tube nomme %s existe deja, ce qui ne devrait jamais arriver puisqu'on cree un tube dedie pour chaque client ==> le serveur s'arrete", nomTube); } /* Connexion au point d'accès client et réponse */ fdW = open(pmsg->infoSup.pointAcces, O_WRONLY); if (fdW == -1) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "Impossible de se connecter au tube %s", pmsg->infoSup.pointAcces); reponse.typ = CONNEXION_OK; strncpy(reponse.infoSup.pointAcces, nomTube, TAILLE_POINT_ACCES); reponse.infoSup.pointAcces[TAILLE_POINT_ACCES-1]='\0'; nbWrite = write(fdW, &reponse, sizeof(reponse)); if (nbWrite < sizeof(reponse)) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "Pb ecriture sur tube nomme %s", pmsg->infoSup.pointAcces); /* Ouverture de ce tube nommé */ fdR = open(nomTube, O_RDONLY); if (fdR == -1) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "open tube pour requetes client-->serveur"); /* Attente et traitement d'une requete du client */ do{ int nbRead = read(fdR, &requete, sizeof(requete)); if (nbRead != sizeof(requete)) { /* Le client a ferme le tube : on sort */ break; } /* On traite la requête */ if ((feof(f) == 0) && (fgets(mEtMme, sizeof(mEtMme), f) != NULL)) { reponse.typ = REQUETE_OK; strncpy(reponse.infoSup.mEtMme, mEtMme, TAILLE_M_ET_MME); } else { reponse.typ = REQUETE_KO; } nbWrite = write(fdW, &reponse, sizeof(reponse)); if (nbWrite < sizeof(reponse)) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "Pb ecriture sur tube nomme %s", pmsg->infoSup.pointAcces); usleep(50000); }while(1); /* On ferme tout. */ if (fclose(f) < 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "fclose"); if (close(fdR) < 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "close"); if (close(fdW) < 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "close"); /* Ce tube ne sera plus utilisé : on peut le supprimer. */ if (unlink(nomTube) < 0) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "unlink"); free(pmsg); pthread_exit((void*)0); } int main() { message_t *pmsg; int fdR; int nbRead; /* Création du tube nommé du serveur */ if (mkfifo(NOM_POINT_ACCES_SERV, S_IRUSR|S_IWUSR) < 0) { if (errno != EEXIST) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "mkfifo(%s)", NOM_POINT_ACCES_SERV); else error_at_line(0, errno, __FILE__, __LINE__, "mkfifo(%s) ==> ce tube existe deja\nOn suppose que c'est un pipe nomme et qu'on peut continuer le programme sans probleme", NOM_POINT_ACCES_SERV); } /* Ouverture de ce tube nommé (equivalent a une ouverture de connexion). NB : On l'ouvre en RDWR et pas en RDONLY, car (cf. Blaess) : si nous ouvrons le client en lecture seule, à chaque fois que le client se termine, la lecture du tube nomme va echouer car le noyau detecte une fermeture de fichier. En demandant un tube en lecture et en ecriture, nous evitons ce genre de situation, car il reste toujours au moins un descripteur ouvert sur la sortie */ fdR = open(NOM_POINT_ACCES_SERV, O_RDWR); if (fdR == -1) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "open(%s)", NOM_POINT_ACCES_SERV); /* Attente de requêtes */ do{ pthread_t thread; int rc; pmsg = malloc(sizeof(message_t)); if (pmsg == NULL) error_at_line(EXIT_FAILURE, 0, __FILE__, __LINE__, "malloc a des problemes (probablement plus de memoire)"); nbRead = read(fdR, pmsg, sizeof(message_t)); if (nbRead != sizeof(message_t)) error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "read sur tube nomme %s KO", NOM_POINT_ACCES_SERV); /* On fait traiter la requête par un thread pour se remettre tout de */ /* suite à l'écoute d'une demande. */ rc = pthread_create(&thread, NULL, traiterConnexion, (void *)pmsg); if (rc < 0) error_at_line(EXIT_FAILURE, rc, __FILE__, __LINE__, "pthread_create"); }while(1); }