#include #include #include #include #include #include #include #include #include #include #include "fonctions.h" #include "entrees_sorties.h" #define TAILLE_V 10 #define NOMTUBESERVEUR "./serveur-rpc" /* nom du tube pour les communications serveur->client */ char nomTubeClient[80]; /* nom du tube pour les communications client->serveur */ char nomTubeClient_serveur[80]; int fdW_connexion; /* fd pour la connexion a un serveur */ int fdR; /* fd pour les communications serveur->client */ int fdW; /* fd pour les communications client->serveur */ int mutex; /* mutex pour l'établissement de la connexion */ void mutex_lock() { struct sembuf op; op.sem_num = 0; op.sem_op = -1; op.sem_flg = 0; if (semop(mutex, &op, 1) == -1){ perror("semop"); exit(EXIT_FAILURE); } } void mutex_unlock() { struct sembuf op = {0, 1, 0}; if (semop(mutex, &op, 1) == -1){ perror("semop"); exit(EXIT_FAILURE); } } #define CLE_MUTEX 42 void mutex_init() { /* Création du sémaphore */ mutex = semget(CLE_MUTEX, 1, IPC_CREAT|0666); if (mutex == -1) { perror("semget"); exit(EXIT_FAILURE); } /* Intialisation du sémaphore au nombre de places dans le parking */ if (semctl(mutex, 0, SETVAL, 1) == -1) { perror("semctl"); exit(EXIT_FAILURE); } } double call_somme(double a, double b) { printf("Appel a distance de somme(%lf, %lf)\n", a, b); /* etablissement de la connexion: on envoie le nom du tube par lequel on va envoyer les prochaines commandes */ mutex_lock(); write_str(fdW_connexion, nomTubeClient_serveur, 80); mutex_unlock(); /* envoi des autres informations sur le tube privé */ write_int(fdW, SOMME); write_str(fdW, nomTubeClient, 80); write_double(fdW, a); write_double(fdW, b); double res = read_double(fdR); return res; } double call_mul(double a, double b) { printf("Appel a distance de mul(%lf, %lf)\n", a, b); mutex_lock(); write_str(fdW_connexion, nomTubeClient_serveur, 80); mutex_unlock(); write_int(fdW, MUL); write_str(fdW, nomTubeClient, 80); write_double(fdW, a); write_double(fdW, b); double res = read_double(fdR); return res; } /* res = a + b * a, b et res sont des vecteurs de meme taille */ void call_sommev(struct vecteur *a, struct vecteur *b, struct vecteur *res) { printf("Appel a distance de sommev\n"); mutex_lock(); write_str(fdW_connexion, nomTubeClient_serveur, 80); mutex_unlock(); write_int(fdW, SOMMEV); write_str(fdW, nomTubeClient, 80); write_vecteur(fdW, a); write_vecteur(fdW, b); read_vecteur_allocated(fdR, res); } /* calcule a.b * a et b sont des vecteurs de meme taille */ double call_mulv(struct vecteur *a, struct vecteur *b) { printf("Appel a distance de mulv\n"); mutex_lock(); write_str(fdW_connexion, nomTubeClient_serveur, 80); mutex_unlock(); write_int(fdW, MULV); write_str(fdW, nomTubeClient, 80); write_vecteur(fdW, a); write_vecteur(fdW, b); return read_double(fdR); } void tester() { double a = 14.5; double b = 18.5; /* test de la fonction somme */ double res_somme = call_somme(a, b); double verif_somme = somme(a, b); if(verif_somme != res_somme ) { fprintf(stderr, "Erreur dans la fonction somme\n"); fprintf(stderr, "\tle calcul local donne %lf\n", verif_somme); fprintf(stderr, "\tle calcul recu donne %lf\n", res_somme); exit(EXIT_FAILURE); } else { printf("test de somme: OK\n"); } /* test de la fonction mul */ double res_mul = call_mul(a, b); double verif_mul = mul(a, b); if(verif_mul != res_mul ) { fprintf(stderr, "Erreur dans la fonction mul\n"); fprintf(stderr, "\tle calcul local donne %lf\n", verif_mul); fprintf(stderr, "\tle calcul recu donne %lf\n", res_mul); exit(EXIT_FAILURE); } else { printf("test de mul: OK\n"); } struct vecteur *v1 = new_vecteur(TAILLE_V); struct vecteur *v2 = new_vecteur(TAILLE_V); int i; for(i=0; ivalues[i]=i%5; v2->values[i]=i%3; } /* test de la fonction sommev */ struct vecteur* res_sommev = new_vecteur(TAILLE_V); struct vecteur* verif_sommev = new_vecteur(TAILLE_V); call_sommev(v1, v2, res_sommev); sommev(v1, v2, verif_sommev); if(! vecteur_egal(verif_sommev, res_sommev) ) { fprintf(stderr, "Erreur dans la fonction sommev\n"); fprintf(stderr, "\tle calcul local donne"); print_v(verif_sommev); fprintf(stderr, "\tle calcul recu donne"); print_v(res_sommev); exit(EXIT_FAILURE); } else { printf("test de sommev: OK\n"); } /* test de la fonction mulv */ double res_mulv = call_mulv(v1, v2); double verif_mulv = mulv(v1, v2); if(verif_mulv != res_mulv ) { fprintf(stderr, "Erreur dans la fonction mulv\n"); fprintf(stderr, "\tle calcul local donne %lf\n", verif_mulv); fprintf(stderr, "\tle calcul recu donne %lf\n", res_mulv); exit( EXIT_FAILURE ); } else { printf("test de mul: OK\n"); } } int main(int argc, char**argv) { int nbRead, nbWrite; mutex_init(); /* Préparation de nomTubeClient (tube qui permettra les communications */ /* serveur-client) */ sprintf(nomTubeClient, "/tmp/client-rpc.%d", getpid()); sprintf(nomTubeClient_serveur, "/tmp/serveur-rpc.%d", getpid()); /* Création du tube nommé qui permettra au serveur de repondre au client */ if (mkfifo(nomTubeClient, 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", nomTubeClient ); printf("et qu'on peut continuer le programme sans probleme\n"); puts(""); } } /* Ouverture de ce tube */ fdR = open(nomTubeClient, O_RDWR); if (fdR == -1) { perror("open(tube nommé)"); exit(EXIT_FAILURE); } /* Création d'un tube nommé qui permettra les communications client --> server */ if (mkfifo(nomTubeClient_serveur, 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", nomTubeClient_serveur ); printf("et qu'on peut continuer le programme sans probleme\n"); puts(""); } } /* Ouverture de ce tube */ fdW = open(nomTubeClient_serveur, O_RDWR); if (fdW == -1) { perror("open(tube nommé)"); exit(EXIT_FAILURE); } /* ouverture du tube par lequel on etablit les connexion */ fdW_connexion = open(NOMTUBESERVEUR, O_WRONLY); if (fdW_connexion == -1) { perror("open(NOMTUBESERVEUR)"); exit(EXIT_FAILURE); } tester(); close(fdW_connexion); close(fdW); close(fdR); /* On détruit le tube nommé du client (puisque ce tube nommé ne servira */ /* plus jamais. */ if (unlink(nomTubeClient) < 0) { perror("unlink"); exit(EXIT_FAILURE); } return EXIT_SUCCESS; }