@ -7,97 +7,98 @@
# include <netdb.h>
# include <netdb.h>
# define BUF_SIZE 500
# define BUF_SIZE 500
# define MAX_CON 5 /* nombre maximum de connexions */
struct addrinfo * result ; // tableau des adresses réseaux des clients
struct addrinfo * result ; /* tableau des adresses réseaux des clients */
int cree_socket ( struct addrinfo hints , char * port ) {
void cree_socket ( struct addrinfo hints , char * port ) {
int s = getaddrinfo ( NULL , port , & hints , & result ) ;
int s = getaddrinfo ( NULL , port , & hints , & result ) ;
if ( s ! = 0 ) {
if ( s ! = 0 ) {
fprintf ( stderr , " getaddrinfo: %s \n " , gai_strerror ( s ) ) ;
fprintf ( stderr , " getaddrinfo: %s \n " , gai_strerror ( s ) ) ;
s = 1 ;
exit ( EXIT_FAILURE ) ;
}
}
return s ;
}
}
void con_client ( int * sfd ) {
void con_client ( int * sfd ) {
struct addrinfo * rp ; // structure de l'adresse du client
struct addrinfo * rp ; /* structure de l'adresse du client */
/* getaddrinfo () retourne une liste de structures d'adresses.
/* getaddrinfo () retourne une liste de structures d'adresses.
Essayez chaque adresse jusqu ' à ce que nous ayons r é ussi à bind ( 2 ) .
Essayez chaque adresse jusqu ' à ce que nous ayons r é ussi à bind ( 2 ) .
Si socket ( ) ( ou bind ( ) ) é choue , nous ( fermons le socket et )
Si socket ( ) ( ou bind ( ) ) é choue , nous ( fermons le socket et )
essayons l ' adresse suivante */
essayons l ' adresse suivante */
for ( rp = result ; rp ! = NULL ; rp = rp - > ai_next ) {
for ( rp = result ; rp ! = NULL ; rp = rp - > ai_next ) {
// socket crée un point de communication et renvoie un descripteur
/* socket crée un point de communication et renvoie un descripteur */
* sfd = socket ( rp - > ai_family , rp - > ai_socktype , rp - > ai_protocol ) ;
* sfd = socket ( rp - > ai_family , rp - > ai_socktype , rp - > ai_protocol ) ;
if ( * sfd = = - 1 ) {
if ( * sfd = = - 1 ) {
continue ;
continue ;
}
}
if ( bind ( * sfd , rp - > ai_addr , rp - > ai_addrlen ) = = 0 ) {
if ( bind ( * sfd , rp - > ai_addr , rp - > ai_addrlen ) = = 0 ) {
break ; // Succès
break ; /* Succès */
}
}
close ( * sfd ) ;
close ( * sfd ) ;
}
}
if ( rp = = NULL ) { // Aucune adresse n'a pu marcher
if ( rp = = NULL ) { /* Aucune adresse n'a pu marcher */
fprintf ( stderr , " Could not bind \n " ) ;
fprintf ( stderr , " Could not connect \n " ) ;
exit ( EXIT_FAILURE ) ;
}
if ( listen ( * sfd , MAX_CON ) = = - 1 ) {
fprintf ( stderr , " erreur du listen " ) ;
exit ( EXIT_FAILURE ) ;
exit ( EXIT_FAILURE ) ;
}
}
freeaddrinfo ( result ) ; /* libère la structure d'adresse client */
}
}
void traite_connexion ( int sfd , int s ) {
void traite_connexion ( int * sfd ) {
ssize_t nread ;
ssize_t nread ;
char buf [ BUF_SIZE ] ;
char buf [ BUF_SIZE ] ;
struct sockaddr_storage peer_addr ;
struct sockaddr_storage peer_addr ;
socklen_t peer_addr_len ;
socklen_t peer_addr_len ;
// Lit les datagrammes et les renvoi au client
int s , new_sfd ;
char host [ NI_MAXHOST ] , service [ NI_MAXSERV ] ;
/* Lit les messages et les renvoi au client */
for ( ; ; ) {
for ( ; ; ) {
peer_addr_len = sizeof ( struct sockaddr_storage ) ;
peer_addr_len = sizeof ( struct sockaddr_storage ) ;
nread = recvfrom ( sfd , buf , BUF_SIZE , 0 , ( struct sockaddr * ) & peer_addr , & peer_addr_len ) ;
new_sfd = accept ( * sfd , ( struct sockaddr * ) & peer_addr , & peer_addr_len ) ; /* accepte la connexion */
nread = read ( new_sfd , buf , BUF_SIZE ) ; /* lit dans le buffer de la connexion, renvoie la taille du message */
if ( nread = = - 1 ) {
if ( nread = = - 1 ) {
continue ;
continue ; /* ignore la mauvaise requete */
/* ignore la mauvaise requete */
}
}
char host [ NI_MAXHOST ] , service [ NI_MAXSERV ] ;
s = getnameinfo ( ( struct sockaddr * ) & peer_addr , peer_addr_len , host , NI_MAXHOST , service , NI_MAXSERV , NI_NUMERICSERV ) ;
s = getnameinfo ( ( struct sockaddr * ) & peer_addr , peer_addr_len , host , NI_MAXHOST , service , NI_MAXSERV , NI_NUMERICSERV ) ;
if ( s = = 0 ) {
if ( s = = 0 ) {
printf ( " Recu %ld octets de %s:%s \n " , ( long ) nread , host , service ) ;
printf ( " Recu %ld octets de %s:%s \n " , ( long ) nread , host , service ) ;
if ( write ( new_sfd , buf , nread ) ! = nread ) {
fprintf ( stderr , " Erreur d'envoi de la reponse \n " ) ;
}
close ( new_sfd ) ; /* ferme la connexion */
}
}
else {
else {
fprintf ( stderr , " getnameinfo: %s \n " , gai_strerror ( s ) ) ;
fprintf ( stderr , " getnameinfo: %s \n " , gai_strerror ( s ) ) ;
}
}
if ( sendto ( sfd , buf , nread , 0 , ( struct sockaddr * ) & peer_addr , peer_addr_len ) ! = nread ) {
fprintf ( stderr , " Erreur d'envoi de la reponse \n " ) ;
}
}
}
}
}
int main ( int argc , char * argv [ ] ) {
int main ( int argc , char * argv [ ] ) {
struct addrinfo hints ;
struct addrinfo hints ;
int s ; // s code de retour de getaddrinfo
int s ; /* s code de retour de getaddrinfo */
int sfd ; // code de retour de l'ouverture du socket
int sfd ; /* code de retour de l'ouverture du socket */
if ( argc ! = 2 ) { // test du nombre d'arguments entrés
if ( argc ! = 2 ) { /* test du nombre d'arguments entrés */
fprintf ( stderr , " Usage: %s port \n " , argv [ 0 ] ) ;
fprintf ( stderr , " Usage: %s port \n " , argv [ 0 ] ) ;
exit ( EXIT_FAILURE ) ;
exit ( EXIT_FAILURE ) ;
}
}
char * port = argv [ 1 ] ; // récupération du port passée en paramètre du programme
char * port = argv [ 1 ] ; /* récupération du port passée en paramètre du programme */
// remplissage de la structure hints contenants la configuration réseau du serveur
/* remplissage de la structure hints contenants la configuration réseau du serveur */
memset ( & hints , 0 , sizeof ( struct addrinfo ) ) ;
memset ( & hints , 0 , sizeof ( struct addrinfo ) ) ;
hints . ai_family = AF_UNSPEC ; // utilisation du serveur sur IPv4/v6 (AF_INET/AF_INET6)
hints . ai_family = AF_UNSPEC ; /* utilisation du serveur sur IPv4/v6 (AF_INET/AF_INET6) */
hints . ai_socktype = SOCK_DGRAM ; // socket en mode datagramme
hints . ai_socktype = SOCK_STREAM ; /* socket en mode datagramme */
hints . ai_protocol = IPPROTO_TCP ; /* protocol de connexion */
s = cree_socket ( hints , port ) ; // création du socket
if ( s = = 1 ) {
exit ( EXIT_FAILURE ) ;
}
con_client ( & sfd ) ;
freeaddrinfo ( result ) ; // libère la structure d'adresse client
traite_connexion( sfd , s ) ;
cree_socket ( hints , port ) ; /* création du socket */
con_client ( & sfd ) ; /* connexion au client */
traite_connexion ( & sfd ) ;
}
}