L3 informatique TP Réseaux n o 4 : Programmation client-serveur en C Sovanna Tan Octobre 2009 1/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
Plan 1 Les fonctions pour les sockets 2 TCP 3 UDP /27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
Sources Internetworking with TCP/IP volume 3 : Client-Server Programming and Applications, Douglas E. Commer and David L. Stevens, Prentice-Hall, 1993. Power Programming with RPC, John Bloomer, O Reilly, 1992. http://www.commentcamarche.net/contents/sockets/ sockintro.php3 3/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
1 Les fonctions pour les sockets 2 TCP 3 UDP /27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
socket close Création d un socket int socket(int domain,int type,int protocol); domain : AF_INET pour Internet IPV4 type : SOCK_STREAM : TCP SOCK_DGRAM : UDP protocol : O pour IP, valeurs définies dans /etc/protocols Valeur de retour : descripteur de fichier du socket Fermeture d un socket int close(int fd); fd : descripteur de fichier du socket 5/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
bind Lien du socket avec une adresse IP et un port struct sockaddr_in { short sin_family; /* must be AF_INET */ u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; ; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd : descripteur de fichier du socket addr : structure contenant les paramètres de connexion addrlen : longueur de la structure utilisée pour addr 6/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
listen accept Mettre un socket en attente de connexion (mode passif) int listen(int sockfd, int backlog); sockfd : descripteur de fichier du socket backlog : longueur maximale de la queue pour les connexions en attente Autoriser les demandes de connexion int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); sockfd : descripteur de fichier du socket addr : structure contenant les paramètres de connexion addrlen : longueur de la structure utilisée pour addr Valeur de retour : nouveau descripteur de fichier pour le socket qui accepte les connexions 7/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
getsockname connect Obtenir un pointeur sur la structure adresse liée au socket int getsockname(int s, struct sockaddr *name, socklen_t *namelen); s : descripteur de fichier du socket name : structure contenant les paramètres de connexion namelen : longueur de la structure utilisée pour addr Demande de connexion à un serveur int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); sockfd : descripteur de fichier du socket serv_addr : structure contenant l adresse du serveur addrlen : longueur de la structure utilisée pour serv_addr 8/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
gethostbyname gethostbyaddr : obtenir des informations réseau sur une machine Obtenir des informations réseau sur une machine struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses */ ; struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); name : nom ou adresse IPV4 addr : structure contenant l adresse len : longueur de la structure type : type de la structure AF_INET ou AF_INET6 /27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation client
read write Lecture/Ecriture de données en mode connecté ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); fd : descripteur de fichier du socket buf : pointeur sur le buffer count : nombre maximal d octets à lire/écrire Valeur de retour : nombre d octets lus/écrits 10/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
recvfrom sendto Lecture/Ecriture de données en mode datagramme ssize_t sendto(int s,const void *buf,size_t len, int flags,const struct sockaddr *to,socklen_t tolen); ssize_t recvfrom(int s,void *buf,size_t len, int flags,struct sockaddr *from,socklen_t *fromlen); s : descripteur de fichier du socket buf : pointeur sur le buffer t : nombre d octets du buffer flags : OU exclusif de drapeaux to/from : adresse du socket destination/source tolen/fromlen : taille de l adresse du socket source/destination Valeur de retour : nombre d octets lus/écrits 11/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
htons inet ntoa Changer l ordre des octets uint16_t htons(uint16_t hostshort); Convertit l ordre des octets de Least Significant Byte First (octet de piods faible d abord) utilisé sur l hôte vers Most Significant Byte First (octet de poids fort d abord) utilisé dans les réseaux. Obtenir une adresse IP sous forme décimale char *inet_ntoa(struct in_addr in); in : structure contenant l adresse Valeur de retour : chaîne de caractères contenant l adresse notée avec des entiers en base 10 et des points 12/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
1 Les fonctions pour les sockets 2 TCP 3 UDP 3/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Programmer les sockets TCP Image provenant de http://www.tenouk.com/module39a.html 14/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur TCP serv.c (1) #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFSZ 100 main(argc, argv) int argc; char **argv;{ struct sockaddr_in sin, from; /* adresse de sockets internet */ struct sockaddr_in *ptr; struct sockaddr addr; /* adresse de socket generique */ int s,g; /* descripteur de socket */ int len=sizeof(from); char diagbuf[bufsz]; /* buffer de dialogue */ int addrlen=sizeof(addr); 15/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur TCP serv.c (2) int rc; int NbAppel =0; /* compteur */ int NbByte =0; /* nombre d octets recus */ bzero((char*) &sin, sizeof(sin)); sin.sin_family=af_inet; /* domaine internet */ sin.sin_addr.s_addr=inaddr_any; /* accepte tous les clients */ sin.sin_port=0; /* systeme donne un port libre */ if((s=socket(af_inet, SOCK_STREAM, 0))<0){ perror("socket"); exit(3); if(bind(s,(struct sockaddr *)&sin,sizeof(sin)) <0){ perror("erreur de bind\n"); exit(6); 16/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur TCP serv.c (3) if((rc=getsockname(s, &addr, &addrlen)) <0){ perror("erreur socket\n"); exit(7); ptr=(struct sockaddr_in *) &addr; printf("on m a assigne le port %d\n",htons(ptr->sin_port)); listen(s,5); printf("attente de demande de connexion\n"); while(1){ g=accept(s,(struct sockaddr *)&from,&len); NbAppel++;; printf("connexion etablie canal %d, appel no %d\n",g,nbappel); if(g<0){ perror("accept"); continue; 17/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur TCP serv.c (4) switch(fork()){ case -1: perror("fork echoue\n"); exit(4); case 0: close(s); printf("debut du processus serveur pour l appel %d\n",nbappel); sprintf(diagbuf,"appel no %d\n",nbappel); write(g,diagbuf,strlen(diagbuf)); while(nbbyte=read(g,diagbuf,bufsz-1)){ printf("de l appel no %d: %s (long %d)\n",nbappel,diagbuf, strlen(diagbuf)); bzero(diagbuf,bufsz); printf("fin du processus serveur pour l appel %d\n",nbappel); close(g); exit(0); default: ; 18/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Client TCP clie.c (1) #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFSZ 100 main(argc, argv) int argc; char **argv;{ struct sockaddr_in sin, pin; /* adresse de sockets internet */ struct hostent *hp; /* adresse du serveur */ int s; /* descripteur de socket */ char diagbuf[bufsz]; /* buffer de dialogue */ if((hp=gethostbyname(argv[1]))==0){ perror("gethostbyname"); exit(1); bzero((char*) &pin, sizeof(pin)); pin.sin_family=af_inet; 19/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Client TCP clie.c (2) pin.sin_addr.s_addr=((struct in_addr *)(hp->h_addr))->s_addr; pin.sin_port=htons(atoi(argv[2])); if((s=socket(pf_inet, SOCK_STREAM, 0))<0){ perror("socket"); exit(1); if(connect(s,(struct sockaddr *) &pin,sizeof(pin)) == -1){ perror("connect"); exit(1); bzero(diagbuf,bufsz); read(s,diagbuf,bufsz-1); printf("%s (long %d)\n",diagbuf,strlen(diagbuf)); bzero(diagbuf,bufsz); sprintf(diagbuf,"je suis un client\n"); write(s,diagbuf,strlen(diagbuf)); bzero(diagbuf,bufsz); sprintf(diagbuf,"bye\n"); write(s,diagbuf,strlen(diagbuf)); close(s); 20/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
1 Les fonctions pour les sockets 2 TCP 3 UDP 1/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Programmer les sockets UDP Image provenant de http://www.tenouk.com/module39a.html 22/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur UDP userv.c (1) #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFSZ 100 main(argc, argv) int argc; char **argv;{ struct sockaddr_in sin; /* adresse de sockets internet */ struct sockaddr_in *ptr; struct sockaddr addr,from; /* adresse de socket generique */ int s,g; /* descripteur de socket */ int fromlen=sizeof(from); char diagbuf[bufsz]; /* buffer de dialogue */ int addrlen=sizeof(addr); struct hostent *hp, *gethostbyaddr(); int rc; int NbAppel =0; /* compteur */ int NbByte =0; /* nombre d octets recus */ 23/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur UDP userv.c (2) bzero((char*) &sin, sizeof(sin)); sin.sin_family=af_inet; /* domaine internet */ sin.sin_addr.s_addr=inaddr_any; /* accepte tous les clients */ sin.sin_port=0; /* systeme donne un port libre */ if((s=socket(af_inet, SOCK_DGRAM, 0))<0){ perror("socket"); exit(3); if(bind(s,(struct sockaddr *)&sin,sizeof(sin)) <0){ perror("erreur de bind\n"); exit(6); if((rc=getsockname(s, &addr, &addrlen)) <0){ perror("erreur socket\n"); exit(7); 24/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Serveur UDP userv.c (3) ptr=(struct sockaddr_in *) &addr; printf("on m a assigne le port %d\n",htons(ptr->sin_port)); bzero(diagbuf,bufsz); while(nbbyte=recvfrom(s,diagbuf,bufsz-1,0,&from,&fromlen)){ ptr=(struct sockaddr_in *) &from; if(hp=gethostbyaddr((char *)&ptr->sin_addr,4,af_inet)){ printf("from host: %s ",hp->h_name); printf("from host: %s ", inet_ntoa(ptr->sin_addr)); else printf("from host: %s ", inet_ntoa(ptr->sin_addr)); printf("from port: %d\n", htons(ptr->sin_port)); printf("received: %s\n",diagbuf); bzero(diagbuf,bufsz); sprintf(diagbuf,"recu"); sendto(s,diagbuf,4,0, &from,sizeof(sin)); bzero(diagbuf,bufsz); 25/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Client UDP uclie.c (1) #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFSZ 100 main(argc, argv) int argc; char **argv;{ struct sockaddr_in sin, pin; /* adresse de sockets internet */ struct sockaddr addr,from; int fromlen=sizeof(from); struct hostent *hp; /* adresse du serveur */ int s; /* descripteur de socket */ char diagbuf[bufsz]; /* buffer de dialogue */ int i; if((hp=gethostbyname(argv[1]))==0){ perror("gethostbyname"); exit(1); 26/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien
Client UDP uclie.c (2) bzero((char*) &pin, sizeof(pin)); pin.sin_family=af_inet; pin.sin_addr.s_addr=((struct in_addr *)(hp->h_addr))->s_addr; pin.sin_port=htons(atoi(argv[2])); if((s=socket(af_inet, SOCK_DGRAM, 0))<0){ perror("socket"); exit(1); bzero(diagbuf,bufsz); for(i=0;i<100;i++){ sprintf(diagbuf,"coucou"); sendto(s,diagbuf,6,0, (struct sockaddr *) &pin,sizeof(pin)); bzero(diagbuf,bufsz); recvfrom(s,diagbuf,bufsz-1,0,&from,&fromlen); printf("%s fin \n",diagbuf); close(s); 27/27 Sovanna Tan L3 informatique TP Réseaux n o 4 : Programmation clien