/* echo / serveur multi-session (select) CMI -- Master Informatique 2007 Emmanuel Godard Cf man select et surtout man select_tut */ #include #include #include #include #include #include #include #include #include /* taille maximale des tampons */ #define MAXT 512 /* nombre maximal de session en parallèle */ #define NBMAX 1024 #define CIAO "Au revoir ...\n" #undef max #define max(x,y) ((x) > (y) ? (x) : (y)) void echo(int * fd, char * hote, int port, int * compteur, int i); int main(int argc, char *argv[]) { int s,r; /* descripteurs de socket */ int on,i,n; /* utilitaires divers */ struct sockaddr_in saddr; /* adresse de socket de type internet */ struct sockaddr_in client; /* adresse socket du client */ unsigned int len=sizeof(struct sockaddr); int nb=0; int sport; char * hote[NBMAX]; int port[NBMAX]; int fd[NBMAX]; int compteur[NBMAX]; fd_set rd, wr, er; /* ensembles de desc. de fichier pour select */ /* Traitement des arguments */ if (argc!=2) { /* erreur de syntaxe */ printf("usage: %s port\n",argv[0]); exit(1); } sport=atoi(argv[1]); fprintf(stderr,"Ecoute sur le port %i\n",sport); /* Initialisation de l'adresse socket */ saddr.sin_family = AF_INET; /* protocole */ saddr.sin_addr.s_addr = INADDR_ANY; /* toute interface */ saddr.sin_port = htons(sport); /* port */ /* Création de la socket, de type TCP / IP */ if ((s=socket(PF_INET,SOCK_STREAM,0))<0) { perror("allocation de socket"); exit(2); } fprintf(stderr,"le n° de la socket est : %i\n",s); /* on rend le port réutilisable rapidement */ on = 1; if (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0) { perror("option socket"); exit(3); } fprintf(stderr,"Option(s) OK!\n"); /* attachement de la socket s à l'adresse saddr */ if (bind(s,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in))<0) { perror("binding"); exit(4); } fprintf(stderr,"bind!\n"); /* la socket est prête à recevoir */ if (listen(s,5)<0) { perror("listen"); exit(5); } fprintf(stderr,"listen!\n"); /* attendre et gérer indéfiniment les connexions entrantes */ FD_ZERO (&wr); FD_ZERO (&er); /* on omettra les données hors bande */ while(1) { /* Indéfiniment */ /* descripteurs à surveiller */ FD_ZERO (&rd); FD_SET (s, &rd); /* toujours surveiller la socket s */ n = max (n, s); for(i=0;i 0) && (FD_ISSET (fd[i],&rd)) ) echo(fd,hote[i],port[i],compteur,i); } } void echo(int * fd, char * hote, int port, int * compteur, int i) { ssize_t lu; /* nb d'octets reçus */ char buf[MAXT]; char tampon[MAXT]; /* tampons pour les communications */ int pid = getpid(); /* pid du processus */ int f = fd[i]; lu = recv(f,tampon,MAXT,0); if (lu > 0 ) { compteur[i]++; tampon[lu] = '\0'; /* log */ fprintf(stderr,"[%s:%i](%i): %3i :%s",hote,port,pid,compteur[i],tampon); snprintf(buf,MAXT,"> %s",tampon); /* echo vers le client */ send(f, buf, strlen(buf),0); } else { /* le correspondant a quitté */ send(f,CIAO,strlen(CIAO),0); fd[i] = -1; close(f); fprintf(stderr,"[%s:%i](%i): Terminé.",hote,port,pid); } }