#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#define TAILLE_BUF 128
int descServ;
void panic (const char *msg) {
perror(msg);
exit(1);
}
void fin (int sig) {
int descServ;
if (close (descServ) != -1)
printf("Descripteur bien fermé\n");
exit(0);
}
int main (int argc, char *argv[]) {
int descServ;
int descClient;
int len,max,max_old;
int lg_addr_client = sizeof(struct sockaddr_in);
int lgMsg = TAILLE_BUF;
struct sockaddr_in addrServ;
struct sockaddr_in addrClient;
char *buf = (char*) malloc (TAILLE_BUF);
struct sigaction act;
fd_set read_fd_set, test_fd_set;
descServ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//Quitter proprement par ^C
act.sa_handler = fin;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act,0);
//nommage du serv
addrServ.sin_family = AF_INET;
addrServ.sin_addr.s_addr = htonl(INADDR_ANY); //toutes les adresses possibles du serveur !
addrServ.sin_port = htons(0);
if (bind (descServ,(struct sockaddr *) &addrServ,(sizeof(struct sockaddr_in))) == -1)
panic("Erreur de nommage");
if (getsockname (descServ,(struct sockaddr *) &addrServ,&len) == -1)
panic("Erreur lors de la recuperation du port");
//Affichage des infos serveurs a communiquer aux clients
printf("Infos sur le serveur:\n");
printf("\tPort: %d\n",ntohs(addrServ.sin_port));
//reception des messages des clients:
listen (descServ,SOMAXCONN); //crée une liste d'attente
FD_ZERO(&read_fd_set);
FD_SET(descServ,&read_fd_set);
max = descServ;
for(;;) {
int lus,desc;
test_fd_set = read_fd_set;
printf("serveur en attente -> descMax : %d\n",max);
if (select(max+1,&test_fd_set,(fd_set *) 0,(fd_set *) 0,(struct timeval*) 0) < 1)
panic ("Pb Select");
for (desc = 0;desc < max+1;desc++)
if (FD_ISSET(desc,&test_fd_set)) {
//message sur socket publique -> nv client !
if (desc == descServ) {
descClient = accept (descServ,(struct sockaddr *) &addrClient,&lg_addr_client);
printf(" Nv client: %s : %d -> desc : %d\n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port),descClient);
FD_SET(descClient,&read_fd_set);
if (max < descClient)
max = descClient;
}
//sinon msg d'un ancien client
else {
ioctl(desc,FIONREAD,&lus); //renvoie le nb de caractčres lisibles
if (lus == 0) { //voir Rifflet page 219
printf(" Fermeture du client de desc %d\n",desc);
close(desc);
FD_CLR(desc,&read_fd_set);
// gerer la borne max de recherche des descripteurs
if (desc == max) {
max_old = max;
max = 0;
for (desc = 0; desc < max_old;desc++)
if ((desc>max) && (FD_ISSET(desc,&read_fd_set)))
max = desc;
}
//traitement d'un client courant !!!
else {
read(desc,buf,TAILLE_BUF);
printf(" Message %s recu du client de desc %d \n",buf,desc);
}
}
}
}
}
}
/* Particulierement interessant quand les clients
sont longs a faire des requetes -> attente saisie
utilisateur par exemple
*/
syntax highlighted by Code2HTML, v. 0.9.1