/* déclaration des types de base */ #include /* constantes relatives aux domaines, types et protocoles */ #include /* constantes et structures propres au domaine INTERNET */ #include /* structures retournées par les fonctions de gestion de la base de données du réseau */ #include /* pour les entrées/sorties */ #include /* la lib standard */ #include /* pour le fork */ #include /* pour la SHM */ #include #include /* pour la manipulation des strings */ #include /* pour le read permissif */ #define SIZE_MAX 32767 // Pour la SHM union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; // L'adresse de la SHM en variable globale pour qu'elle soit accessible depuis les fonctions int * addr_shm; // fonctions de manipulation de la SHM void print_shm() { printf("La valeur est : %d\n", *addr_shm); } void add(int n) { *addr_shm += n; } void sub(int n) { *addr_shm -= n; } void mul(int n) { *addr_shm *= n; } void divi(int n) { *addr_shm /= n; } void reset() { *addr_shm = 0; } int get() { return *addr_shm; } // affichage du nombre de connexions void print_nb_connexions(int nb_connexions) { if (nb_connexions == 1) { printf("Nouvelle connexion, 1ere connexion\n"); } else if (nb_connexions == 2) { printf("Nouvelle connexion, 2nd connexion\n"); } else { printf("Nouvelle connexion, %deme connexion\n", nb_connexions); } printf("L'adresse du nombre de connexions est : %p\n", &nb_connexions); } // Structure pour le traitement des requettes client struct traitement { int action; int arg; }; // Fonction traitant la phrase reçu et renvoyant une structure traitement // Fonction qui sera exploitable struct traitement process(int sock) { char buff[200]; // PRIMITIVE READ TRES MAL UTILISEE VOLONTAIREMENT read(sock, buff, SIZE_MAX); struct traitement ret; if (!strncmp(buff, "PRINT", 5)) { ret.action = 1; } else if (!strncmp(buff, "ADD", 3)) { ret.action = 2; read(sock, buff, SIZE_MAX); ret.arg = atoi(buff); } else if (!strncmp(buff, "SUB", 3)) { ret.action = 3; read(sock, buff, SIZE_MAX); ret.arg = atoi(buff); } else if (!strncmp(buff, "MUL", 3)) { ret.action = 4; read(sock, buff, SIZE_MAX); ret.arg = atoi(buff); } else if (!strncmp(buff, "DIV", 3)) { ret.action = 5; read(sock, buff, SIZE_MAX); ret.arg = atoi(buff); } else if (!strncmp(buff, "RESET", 5)) { ret.action = 6; } else if (!strncmp(buff, "GET", 3)) { ret.action = 7; } else { ret.action = 8; } return ret; } int main(int argc, char * argv[]) { if (argc != 2) { printf("ERREUR : Usage : ./serveur N°Port\n"); exit(2); } // Variable pour le test sur le retour des fonctions des librairies int rt; // Déclaration des clés int key_sema = 327; int key_mem = 328; // Création de la SHM (dans les deux processus) int ma_shm; ma_shm = shmget((key_t)key_mem, sizeof(int), 0666 | IPC_CREAT); if (ma_shm == -1) { perror("ERREUR. Echec shmget((key_t)key_mem, sizeof(int), 0666 | IPC_CREAT) \n"); fprintf(stderr, "ERREUR. Echec shmget((key_t)key, sizeof(int), 0666 | IPC_CREAT) \n"); exit(2); } addr_shm = (int *)shmat(ma_shm, 0, 0); if (addr_shm == NULL) { perror("ERREUR. Echec shmat(ma_shm, 0, 0) \n"); fprintf(stderr, "ERREUR. Echec shmat(ma_shm, 0, 0) \n"); exit(2); } // Initialisation de la SHM *addr_shm = 0; // Création du semaphore (dans les deux processus) int sema; sema = semget((key_t)key_sema, 1, 0666 | IPC_CREAT); if (sema == -1) { perror("ERREUR. Echec semget((key_t)key_sema, 1, 0666 | IPC_CREAT) \n"); fprintf(stderr, "ERREUR. Echec semget((key_t)key, 1, 0666 | IPC_CREAT) \n"); exit(2); } // Initialisation du sémaphore union semun arg; arg.val = 1; rt = semctl(sema, 0, SETVAL, arg); if (rt != 0) { perror("ERREUR. Echec semctl(sema, 0, SETVAL, arg) \n"); fprintf(stderr, "ERREUR. Echec semctl(sema, 0, SETVAL, arg) \n"); exit(2); } // La structure pour manipuler les semaphores struct sembuf buf; buf.sem_flg = 0; buf.sem_num = 0; // On crée le socket local int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("ERREUR lors de la création du socket\n"); exit(1); } // On cree l'adresse du socket local struct sockaddr_in addr_local; int binder; addr_local.sin_family = AF_INET; addr_local.sin_port = atoi(argv[1]); addr_local.sin_addr.s_addr = INADDR_ANY; //On bind l'adresse du socket créee avec le socket local binder = bind(sock,(struct sockaddr *) &addr_local, sizeof(struct sockaddr_in)); if (binder == -1){ printf("ERREUR lors du bind du socket\n"); exit(1); } //Initialisation file d'attente listen(sock, 100); // Variable de stockage de l'addresse emmeteur struct sockaddr_in addr_em; unsigned int longueur_addr_em = sizeof(struct sockaddr_in); // On se met en état d'acceptation de connexion (et on crée un socket en passant) int pid = 1; int nb_connexions = 0; while (pid != 0){ int sock_connexion = accept(sock, (struct sockaddr *)&addr_em, &longueur_addr_em); nb_connexions++; pid = fork(); if (pid == -1){ printf("ERREUR lors du fork\n"); exit(1); } else if (pid == 0) { if (sock_connexion == -1) { printf("ERREUR lors de l'acceptation de la connexion\n"); exit(1); } else { // Recupération du traitement struct traitement taf = process(sock_connexion); // Prise du Semaphore buf.sem_op = -1; rt = semop(sema, &buf, 1); if (rt != 0) { perror("ERREUR. EChec semop(sema, &buf, 1) \n"); fprintf(stderr, "ERREUR. Echec semop(sema, &buf, 1) \n"); exit(2); } // Traitement if (taf.action == 1) { print_shm(); } else if (taf.action == 2) { add(taf.arg); } else if (taf.action == 3) { sub(taf.arg); } else if (taf.action == 4) { mul(taf.arg); } else if (taf.action == 5) { divi(taf.arg); } else if (taf.action == 6) { reset(); } else if (taf.action == 7) { int val = get(); char val_string[10]; sprintf(val_string, "%d", val); send(sock_connexion, val_string, strlen(val_string), 0); } // Libération du Semaphore buf.sem_op = 1; rt = semop(sema, &buf, 1); if (rt != 0) { perror("ERREUR. EChec semop(sema, &buf, 1) \n"); fprintf(stderr, "ERREUR. Echec semop(sema, &buf, 1) \n"); exit(2); } } } } return 0; }