#include #include #include #include #include #include #include #include #include /* -------------------------------------------------------- * * Exemple d'utilisation de select : * Ce serveur scrute simultanément le clavier (stdin) * et des sockets dont le numéro de la première * et le nombre ont ete passés sur la ligne de commande. * * Fonctionnement : * Après avoir créé toutes les sockets, le processus se bloque sur le select * en indiquant qu'il attend un événement sur stdin ou n'importe laquelle des * sockets créées. * Lors de l'occurrence de l'événement, on vérifie d'où il vient, et on prend * les mesures adéquates. * * ----------------------------------------------------------- */ int Sock_Comm[10]; struct sockaddr_in6 Decrit_sock[10]; int main (int argc, char *argv[]) { fd_set Masque_R, Masque_W, Masque_E; int i, Nb_Ports, Prem_Port, Ret_sel; char Nom_Hote[256]; struct hostent Struct_hote, *Ptr_hote; struct timeval Delai; void Creer_Sock (int Num_Sock, int Port); void RAZ_Sock (int socket); void Lire (int socket); if (argc != 3) { printf ("Utilisation : %s Prem_port Nb_ports\n", argv[0]); exit (1); } /* Prendre le nom de la machine locale */ if (gethostname (Nom_Hote, sizeof Nom_Hote)) { perror ("gethostname"); exit (1); } /* Pointeur vers la description du noeud local */ if ((Ptr_hote = gethostbyname2 (Nom_Hote, AF_INET6)) == NULL) { perror ("gethostbyname"); exit (1); } /* sauvegarde */ Struct_hote = *Ptr_hote; /* Ouverture des sockets demandes */ Nb_Ports = atoi (argv[2]); Prem_Port = atoi (...); for (i = 0; i < ...; i++) { Creer_Sock (i, Prem_Port + i); } /* Mise en place du select */ while (1) { printf (" Le serveur de pid %d va attendre sur select\n", (int)getpid ()); FD_ZERO (&Masque_R); FD_ZERO (&Masque_E); FD_ZERO (&Masque_W); /* FD_SET sert a positionner les file descriptors sur lesquels * on attend. * A utiliser pour etre portable, en effet le bit i du masque * ne correspond pas forcement au file descriptor i ! */ FD_SET (0, &Masque_R); for (i = 0; i < Nb_Ports; i++) FD_SET (Sock_Comm[i], &Masque_R); Delai.tv_sec = 30; Delai.tv_usec = 0; Ret_sel = select (32, ..., ..., ..., &Delai); /* cf. man -s 3c select */ switch (Ret_sel) { case -1: { perror ("select"); for (i = 0; i < Nb_Ports; i++) RAZ_Sock (Sock_Comm[i]); exit (1); } case 0: { printf ("Select rend 0 après expiration du délai.\n"); for (i = 0; i < Nb_Ports; i++) RAZ_Sock (Sock_Comm[i]); exit (1); } } /* On a recu qqe chose */ /* verifier si cela vient du clavier... */ if (FD_ISSET (..., &Masque_R)) { char tmp[80]; scanf ("%s", tmp); printf ("\nlu sur le clavier : %s\n", tmp); } /* ou des sockets : */ for (i = 0; i < Nb_Ports; i++) if (FD_ISSET (Sock_Comm[i], &Masque_R)) Lire (Sock_Comm[i]); } /* fin while */ } /**********************Fermer socket ****************************/ void RAZ_Sock (int socket) { printf (" Fermeture du socket %d\n", socket); if (shutdown (..., 2) == -1) perror ("shutdown"); if (close (socket)) perror ("close"); } /***********************Creer socket ****************************/ void Creer_Sock (int Num_Sock, int Port) { int Taille; if ((Sock_Comm[Num_Sock] = socket (AF_INET6, ..., 0)) == -1) { perror ("socket"); exit (1); } Decrit_sock[Num_Sock].sin6_family = AF_INET6; Decrit_sock[Num_Sock].sin6_port = ...; memcpy (&Decrit_sock[Num_Sock].sin6_addr, &in6addr_any, sizeof in6addr_any); printf ("Creer_Sock : socket #%d, port %d\n", Sock_Comm[Num_Sock], ntohs (Decrit_sock[Num_Sock].sin6_port)); Taille = sizeof Decrit_sock[Num_Sock]; if (bind (Sock_Comm[Num_Sock], (struct sockaddr *) &(Decrit_sock[Num_Sock]), Taille)) { perror ("bind"); RAZ_Sock (Sock_Comm[Num_Sock]); } } /******************* Lire socket *********************************/ void Lire (int socket) { int Long_Tab, Long_dist, Drapeaux, Ret_Recv; char Tab[256]; struct sockaddr_in6 Decrit_dist; struct hostent *peer_hent; char *peer = NULL; Long_Tab = sizeof (Tab); Long_dist = sizeof (Decrit_dist); Drapeaux = 0; /* Drapeaux peut inclure: MSG_OOB et/ou MSG_PEEK */ /* Faire man recvfrom pour completer la suite ! * Attention : Long_Tab est un parametre de sortie */ Ret_Recv = recvfrom (..., Tab, Long_Tab, ..., ..., ...); if (Ret_Recv == -1) { perror ("recvfrom"); exit (1); } else { Tab[Ret_Recv] = '\0'; if (!(peer_hent = gethostbyaddr ((char*)&Decrit_dist.sin6_addr, sizeof Decrit_dist.sin6_addr, AF_INET))) peer = "(erreur gethostbyname)"; else peer = strdup (peer_hent->h_name); printf ("-->%s<-- %s\n", peer, Tab); } }