L2 informatique Introduction aux réseaux : Programmation client

Transcription

L2 informatique Introduction aux réseaux : Programmation client
Les fonctions pour les sockets
TCP
UDP
L2 informatique Introduction aux réseaux :
Programmation client-serveur en C
Sovanna Tan
mars 2010
1/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
Plan
2/32
1
Les fonctions pour les sockets
2
TCP
3
UDP
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
4/32
TCP
1
Les fonctions pour les sockets
2
TCP
3
UDP
Sovanna Tan
UDP
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
gethostbyname – gethostbyaddr : obtenir des informations
réseau sur une machine
9/32
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
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmatio
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
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 poids 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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
13/32
TCP
1
Les fonctions pour les sockets
2
TCP
3
UDP
Sovanna Tan
UDP
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Programmer les sockets TCP
Image provenant de http://www.tenouk.com/Module39a.html
14/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec fork : serv.c (1)
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<string.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<netdb.h>
#define BUFSZ 100
int main(int argc, char *argv[]) {
struct sockaddr_in sin, from;
struct sockaddr_in *ptr;
struct sockaddr addr;
int s,g;
int len=sizeof(from);
char diagbuf[BUFSZ];
int addrlen=sizeof(addr);
15/32
Sovanna Tan
/* adresse de sockets internet */
/* adresse de socket generique */
/* descripteur de socket
*/
/* buffer de dialogue
*/
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec fork : serv.c (2)
int rc;
int NbAppel =0;
int NbByte =0;
/* compteur
/* nombre d’octets recus
*/
*/
bzero((char*) &sin, sizeof(sin));
sin.sin_family=AF_INET;
/* domaine internet
*/
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=0;
/* accepte tous les clients
*/
/* 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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec fork : 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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec fork : 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/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec select : selserv.c (1)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFSZ 1024
/* fonction pour lire le message d’un client */
char *lire_message(int sock) {
char *msg = (char *)malloc(BUFSZ * sizeof(char));
int nb_lu;
nb_lu = read(sock, msg, BUFSZ);
if(nb_lu >2){ /* message non vide */
printf("De l’appel no %d: %s (long %ld)\n", sock, msg,strlen(msg)+1);
fflush(stdout);
return msg;
}
else
return NULL;
}
19/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec select : selserv.c (2)
int main(int argc, char *argv[]) {
struct sockaddr_in sin, from;
struct sockaddr_in *ptr;
struct sockaddr addr;
int s,g,fd,c;
int len=sizeof(from);
char diagbuf[BUFSZ];
char accueil[BUFSZ];
int addrlen=sizeof(addr);
int rc;
int NbAppel =0;
bzero((char*) &sin, sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=0;
char *message;
fd_set rfds, afds;
int nfds;
20/32
/* adresse de sockets internet */
/* adresse de socket generique */
/* descripteur de socket
*/
/* buffer de dialogue
/* buffer de dialogue
*/
*/
/* compteur
*/
/* domaine internet
*/
/* accepte tous les clients
*/
/* systeme donne un port libre */
/* rfds est la liste des clients */
/* nfds est la taille de la liste*/
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec select : selserv.c (3)
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);
}
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);
/* initialise liste des clients */
nfds = getdtablesize();
FD_ZERO(&afds);
FD_SET(s, & afds); /* fd_set sert a ajouter un element a la liste */
printf("Initialisation complete\n");
21/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec select : selserv.c (4)
/* gestion des clients */
while(1){
memcpy(&rfds, &afds, sizeof(rfds));
select(nfds, & rfds, 0, 0, 0);
if( FD_ISSET(s, &rfds) ){ /*fd_isset sert a tester si la liste est vide*/
/* connexion d’un client */
g=accept(s,(struct sockaddr *)&from,&len);
NbAppel++;;
printf("Connexion etablie canal %d, appel no %d\n",g,NbAppel);
/* ajout du client dans la liste des clients */
FD_SET(g, &afds);
sprintf(accueil,"Vous etes connecte sur le canal no %d.
\nEcrivez un message vide (appui sur la touche Entree)
pour vous deconnecter.\n", g);
write(g,accueil, strlen(accueil)+1);
}
/* lit le message du client et l’envoie a tout le monde */
for( fd=0; fd<nfds; fd++ )
if( fd != s && FD_ISSET(fd, &rfds) ) {
if( (message = lire_message(fd)) != NULL ) {
22/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur TCP avec select : selserv.c (5)
for( c=0; c<nfds; c++){
if( c!=s && FD_ISSET(c, &afds) ){
sprintf(diagbuf,"Message du canal %d : ", fd);
strcat(diagbuf,message);
write(c, diagbuf, strlen(diagbuf)+1);
}
}
}
else{
close(fd);
FD_CLR(fd, &afds);
printf("\nDeconnexion sur le canal %d.\n\n", fd);
}
}
}
}
23/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Client TCP : clie.c (1)
#include <stdio.h>
include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFSZ 100
int main(int argc, char *argv[]) {
struct sockaddr_in sin, pin;
struct hostent *hp;
int s;
char diagbuf[BUFSZ];
if((hp=gethostbyname(argv[1]))==0){
perror("gethostbyname");
exit(1);
}
bzero((char*) &pin, sizeof(pin));
pin.sin_family=AF_INET;
24/32
Sovanna Tan
/*
/*
/*
/*
adresse de sockets internet
adresse du serveur
descripteur de socket
buffer de dialogue
*/
*/
*/
*/
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
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);
}
25/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
26/32
TCP
1
Les fonctions pour les sockets
2
TCP
3
UDP
Sovanna Tan
UDP
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Programmer les sockets UDP
Image provenant de http://www.tenouk.com/Module39a.html
27/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur UDP : userv.c (1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFSZ 100
int main(int argc, char *argv[]) {
struct sockaddr_in sin;
struct sockaddr_in *ptr;
struct sockaddr addr,from;
int s,g;
int fromlen=sizeof(from);
char diagbuf[BUFSZ];
int addrlen=sizeof(addr);
struct hostent *hp, *gethostbyaddr();
int rc;
int NbAppel =0;
int NbByte =0;
28/32
Sovanna Tan
/* adresse de sockets internet */
/* adresse de socket generique */
/* descripteur de socket
*/
/* buffer de dialogue
*/
/* compteur
/* nombre d’octets recus
*/
*/
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Serveur UDP : userv.c (2)
bzero((char*) &sin, sizeof(sin));
sin.sin_family=AF_INET;
/* domaine internet
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=0;
/* accepte tous les clients
*/
/* 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);
}
29/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
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);
}
}
30/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
Client UDP : uclie.c (1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFSZ 100
int main(int argc, char *argv[]) {
struct sockaddr_in sin, pin;
struct sockaddr addr,from;
int fromlen=sizeof(from);
struct hostent *hp;
int s;
char diagbuf[BUFSZ];
int i;
/* adresse de sockets internet */
/* adresse du serveur
/* descripteur de socket
/* buffer de dialogue
*/
*/
*/
if((hp=gethostbyname(argv[1]))==0){
perror("gethostbyname");
exit(1);
}
31/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat
Les fonctions pour les sockets
TCP
UDP
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);
}
32/32
Sovanna Tan
L2 informatique Introduction aux réseaux : Programmat