269 lines
6.6 KiB
C
269 lines
6.6 KiB
C
/* déclaration des types de base */
|
|
#include <sys/types.h>
|
|
/* constantes relatives aux domaines, types et protocoles */
|
|
#include <sys/socket.h>
|
|
/* constantes et structures propres au domaine INTERNET */
|
|
#include <netinet/in.h>
|
|
/* structures retournées par les fonctions de gestion de la base de
|
|
données du réseau */
|
|
#include <netdb.h>
|
|
/* pour les entrées/sorties */
|
|
#include <stdio.h>
|
|
/* la lib standard */
|
|
#include <stdlib.h>
|
|
/* pour le fork */
|
|
#include <unistd.h>
|
|
|
|
/* pour la SHM */
|
|
#include <sys/shm.h>
|
|
#include <sys/sem.h>
|
|
|
|
/* pour la manipulation des strings */
|
|
#include <string.h>
|
|
|
|
/* 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;
|
|
}
|
|
|