/* * serveur.c * * Rq: open RDWR au lieu de RD_ONLY du tube serveur * pour que le read n'echoue pas a la terminaison du client * en supposant la connexion avec le client terminee. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "client-serveur.h" #define REQUESTS_MAX 10 #define NB_THREADS 4 FILE* f= NULL; pthread_mutex_t f_lock; // lock to be used when accessing f sem_t new_job; // signals that a request is to be processed sem_t available_spot; // signals that a spot is available in the requests array request_t* requests[REQUESTS_MAX]; // requests to be processed int head_requests=0; // where the next request is inserted int tail_requests=0; // where to get the next request pthread_mutex_t requests_mutex; // to protect tail_requests from concurrent accesses response_t search_key(request_t *request) { char ligne[256]; response_t response; /* Calcul response.pointAccesPrive */ strcpy(response.pointAccesPrive, ""); pthread_mutex_lock(&f_lock); /* Le point d'accès privé n'est pas utilisé dans cette appli */ rewind(f); while (feof(f) == 0) { if (fgets(ligne, sizeof(ligne), f) != NULL) { if (strncmp(ligne, request->contenu, strlen(request->contenu)) == 0){ break; } } } if (feof(f) == 0) { strcpy(response.contenu, ligne); response.contenu[strlen(ligne)-1] = '\0'; /* Supprime le '\n' final */ } else { strcpy(response.contenu,"Desole, je ne le connais pas"); } pthread_mutex_unlock(&f_lock); return response; } void process_request(request_t *request){ response_t response; int fdW; int nbWrite; response = search_key(request); /* Affichage */ printf("Serveur a recu \"%s\" et repond \"%s\"\n", request->contenu, response.contenu ); /* Connexion au point d'accès client et réponse */ fdW = open(request->pointAccesClient, O_WRONLY); if (fdW == -1) { perror("open(pointAccessClient)"); exit(EXIT_FAILURE); } nbWrite = write(fdW, &response, sizeof(response)); if (nbWrite < sizeof(response)) { perror("pb ecriture sur pipe nomme"); exit(EXIT_FAILURE); } /* Dans cette application, le client ne renvoie pas de requête ultérieure*/ /* nécessitant une réponse ==> On peut fermer ce tube */ close(fdW); free(request); } void* thread_function(void* arg) { while(1) { int ret = sem_wait(&new_job); // wait until a new job is available assert(ret == 0); request_t* req = NULL; /* takes one of the available requests */ pthread_mutex_lock(&requests_mutex); req = requests[tail_requests]; tail_requests = (tail_requests +1) % REQUESTS_MAX; ret = sem_post(&available_spot); assert(ret == 0); pthread_mutex_unlock(&requests_mutex); process_request(req); } return NULL; } int main() { int fdR; int nbRead; /* Création du tube nommé du serveur */ if (mkfifo(NOMPOINTACCESSERV, S_IRUSR|S_IWUSR) < 0) { if (errno != EEXIST) { perror("mkfifo(tube nommé client"); exit(EXIT_FAILURE); } else { printf("%s existe deja : on suppose que c'est un pipe nomme\n", NOMPOINTACCESSERV ); printf("et qu'on peut continuer le programme sans probleme\n"); puts(""); } } /* Ouverture du fichier mEtMme.txt */ f = fopen("mEtMme.txt", "r"); if (f == NULL) { perror("open(mEtMme.txt)"); exit(EXIT_FAILURE); } /* Ouverture de ce tube nommé (équivalent à une attente de connexion) */ fdR = open(NOMPOINTACCESSERV, O_RDWR); if (fdR == -1) { perror("open(tube nommé)"); exit(EXIT_FAILURE); } pthread_mutex_init(&f_lock, NULL); pthread_t tid[NB_THREADS]; sem_init(&new_job, 0, 0); sem_init(&available_spot, 0, REQUESTS_MAX); pthread_mutex_init(&requests_mutex, NULL); head_requests = 0; tail_requests = 0; for(int i = 0; i