/* Un client */ static void* repeater(void* sck) { int sckt = (int) sck; char buf[MAX_BUFFER]; int nbc, i; const char WELCOME[] = "mtcs : bienvenu\n"; pgrs_in(); write(sckt, WELCOME, strlen(WELCOME)); pgrs("enregistrement d'une socket"); add_socket(sckt); while (1) { pgrs("attente read"); nbc = read(sckt, buf, MAX_BUFFER); if (nbc <= 0) { pgrs("fin lecture client"); pgrs("desenregistrement d'une socket"); del_socket(sckt); close(sckt); pgrs_out(); return NULL; } pgrs("boucle ecriture"); for(i=0; i<MAX_CONNECTION; i++) if (sockets[i]) write(sockets[i], buf, nbc); pgrs("fin boucle ecriture"); } return NULL; }
/* Version stupide. Pas de creation de thread, Le serveur ne peut plus accepter de connexion car il gère l'interaction avec le premier client. */ int manage_cnct(int fd) { pthread_t thread; int result; pgrs_in(); result = pthread_create(&thread,NULL,repeater,(void*)fd); add_socket(fd); /*repeater(fd); */ pgrs_out(); return result; }
static void del_socket(int fd) { int i; pgrs_in(); for (i=0; i<MAX_CONNECTION; i++) { if (sockets[i] == fd) { sockets[i] = 0; break; } } assert(i!=MAX_CONNECTION); pgrs_out(); }
/* Retourne une socket d'écoute sur le port passé en argument (ce numéro de port peut etre modifié si il était déjà utilisé) */ static int open_socket(int *port) { int skfd; /* socket */ struct sockaddr_in name; int try=0; pgrs_in(); /* * « formules magiques » qui vont bien */ /* incantation créant une socket */ skfd = socket(AF_INET, SOCK_STREAM, 0); if (skfd < 0) { perror("ouverture socket ecoute"); exit(EXIT_FAILURE); } name.sin_family = AF_INET; name.sin_addr.s_addr = INADDR_ANY; name.sin_port = htons(*port); pgrs("socket creee"); /* incantation liant la socket au port souhaité */ while (try<MAX_TENTATIVE && bind(skfd, (struct sockaddr*)&name, sizeof(name)) < 0) { try++; (*port)++; name.sin_port = htons(*port); } if (try == MAX_TENTATIVE) { perror("bind de la socket"); exit(EXIT_FAILURE); } pgrs("binding effectue"); /* incantation initialisant la socket en écoute */ if (listen(skfd, MAX_PENDING) != 0) { perror("listen"); exit(EXIT_FAILURE); } pgrs("listen ok"); pgrs_out(); return skfd; } /* Notification d'un refus de connexion sur la socket */ static void noconnect(int socket) { const char NOCONNECT[] = "mtcs : connexion refusee, desole\n"; pgrs_in(); write(socket, NOCONNECT, strlen(NOCONNECT)); close(socket); pgrs_out(); } /* Etablissement, par le serveur, de la connexion d'un client */ static int create_cnct(int skfd) { int skcnct; /* socket de connection */ int status; pgrs_in(); /* on récupère la connexion */ skcnct = accept(skfd, NULL, NULL); if (skcnct < 0) { perror("ne peut etablir la connexion, accept impossible"); exit(EXIT_FAILURE); } /* un thread fils pour gérer cette connexion */ status = manage_cnct(skcnct); if (status < 0) { noconnect(skcnct); pgrs_out(); return -1; } pgrs_out(); return 0; }