linux – principes et programmationgautheron.name/pdf/nsy103-5-reseau.pdf · programmation réseau...
TRANSCRIPT
Linux – Principes et Programmation
5. Programmation réseau
Socket, RPC
CNAM NSY103 2009/2010Yann GAUTHERON
Extraits : http://fr.wikipedia.org/,LINUX Programmation système et réseau (Joëlle DELACROIX)http://www.cnam.fr/
Programmation réseau● Modèle clients serveurs
● Notions
● Interconnexion de réseaux● Quelques principes de base
● Programmation socket● Sous linux● Interfaces● Différents modes de communications (connecté, non connecté)
● Appel de procédure à distance (RPC)● Mécanisme et principe● Les difficultés
Programmation réseau● Modèle client serveur
Programmation réseau● Interconnexion de réseau
Programmation réseau● Interconnexion de réseau
● Structure hiérarchique fondée sur le domaine (DNS)
objet.sous-domaine.domaineex: fermi.cnam.frobjet : nom d'une machine.domaine : géographique (fr, jp) ou institutionnel (com, mil, edu, name)
● Adresses IP : 32 bitsPaire (adresse réseau, adresse machine dans le réseau)
Forme pointée : 10000000 00001010 00000010 00011110128.10.2.30
Programmation réseau● Interconnexion de réseau
● IP : adressage de machine à machine via adresse IP● TCP/UDP : adressage d'applications à applications
– notion de ports (entier 16 bits)
Programmation réseau● Interconnexion de réseau : couche UDP
User Datagram Protocol● Protocole transport de bout en bout
– Adressage d'application à application via les ports UDP– Ports UDP réservés– exemple : port 513 application who
● Protocole transport non fiable basé sur IP– Datagrammes indépendants– Perte de datagrammes– Datagrammes dupliqués– Pas de remise dans l'ordre d'émission– exemple : le courrier
Programmation réseau● Interconnexion de réseau : couche TCP
Transfert Control Protocol● Protocole transport de bout en bout
– Adressage d'application à application via les ports TCP– Ports TCP réservés– exemple : port 21 application FTP
● Protocole transport fiable orienté connexion basée sur IP– Connexion / Flux d'octets– Pas de perte de messages– Pas de duplication– Remise dans l'ordre d'émission– Analogie : le téléphone
Programmation réseau● Interconnexion de réseau
Programmation réseau● Interconnexion de réseau : couche Application
Programmation réseau● Les processus démons réseaux
● Durant toutes ces étapes, le processus inetd est toujours actif
Programmation réseau● Interface socket
● Interface de programmation (ensemble de primitives)● Point de communication (adresse d'application)● Compatible SGF
Programmation réseau● Interface socket : Création
● sock = socket (af, type, protocole);– Famille
● TCP-IP : AF_INET● UNIX : AF_UNIX
– Type de service : SOCK_STREAM, SOCK_DGRAM ou SOCK_RAW– Protocole : IPPROTO_TCP, IPPROTO_UDP ou 0
● int socket (af, type, protocole)int af;int type;int protocole;
– Retourne un descripteur de socket ayant les mêmes propriétés qu'un descripteur de fichier ( héritage )
– Accessible par le créateur et les fils de celui-ci
Programmation réseau● Interface socket : Attachement d'une @ d'application
● int bind (int sock, struct sockaddr_in *p_adresse, int lg);
● sock : descripteur de la socket● p_adresse : Pointeur en mémoire sur l'adresse, dans domaine TCP/IPstruct sockaddr_in
● lg : Longueur de la structure adresse– L'opération d'attachement permet d'étendre le groupe des processus pouvant
accéder à la socket
Programmation réseau● Interface socket : Attachement d'une @ d'application
● struct sockaddr_in {short sin_family; -- AF-INETushort sin_port; -- n° de portstruct in_addr sin_addr; -- @ IPchar sin_zero [8]; -- Huit 0
}– Le numéro de port est un entier en dehors des numéros de port réservés
(>IPPORT_RESERVED). Le champ peut être mis à 0 (Choix laissé au système).
– L'adresse IP de la machine : ● constante INADDR_ANY● utilisation du fichier /etc/hosts ou serveur de noms (DNS)
Programmation réseau● Interface socket : Attachement d'une @ d'application
● /etc/hosts : Correspondance adresse IP et nom symbolique–- Adresse IP, nom symbolique, alias, commentaire163.173.128.6 asimov.cnam.fr cnam iris
● struct hostent {char *h_name; /* nom de la machine */char **h_aliases; /* alias */int h_addrtype; /* type de l'adresse */int h_length; /* longueur de l'adresse */char **h_addr_list; /* liste des adresses IP DNS */#define h_addr h_addr_list[0] /* 1er de la liste IP */
};● Obtenir l'entrée /etc/host de la machine de nom "nom"
struct hostent *gethostbyname (nom)char *nom;
Programmation réseau● Interface socket : Attachement d'une @ d'application
Programmation réseau● Interface socket : Communication en UDP
Programmation réseau● Interface socket : Communication en UDP
● int sendto(sock, msg, lg, option, p_dest, lgdest);– int sock; -- socket d'émission– char *msg; -- @ zone mémoire contenant le message– int lg; -- taille en octets du message– int option; -- 0– struct sockaddr_in *p_dest; -- @ du destinataire– int lgdest; -- taille de l'adresse du destinataire
● int recvfrom(sock, msg, lg, option, p_exp, p_lgexp);– int sock; -- socket de réception– char *msg; -- @ zone mémoire pour recevoir le message– int lg; -- taille en octets du message– int option; -- 0 ou MSG_PEEK– struct sockaddr_in *p_exp; -- @ de l'expéditeur– int *p_lgdest; -- taille de l'@ de l'expéditeur
Programmation réseau● Interface socket : Communication en UDP#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#define PORTS 2058main() { // SERVEUR
int sock, lg, n;char buf[20];struct sockaddr_in adr_s, adr_c;
/* Création socket */sock = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);/* Attachement socket */construit_adresse_locale (adr_s, PORTS); –- adr = INADDR_ANYbind(sock, &adr_s, sizeof(adr_s));for (;;) {
lg = sizeof(adr_c);n = recvfrom (sock, buf, 20, 0, &adr_c, &lg);printf("Chaine reçue %s\n", buf);
}close(sock);
}
Programmation réseau● Interface socket : Communication en UDP#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#define PORTS 2058main() { // CLIENT
struct hostent *h;struct sockaddr_in adr_s,adr_c;char buf[20];int sock;
/* création socket */sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);/* Attachement socket */construit_adresse_locale (adr_c, 0) ; -- adr_c = INADDR_ANYbind(sock, &adr_c, sizeof(adr_c));/* Construction adresse du serveur */h=gethostbyname("fermi.cnam.fr");construit_adresse_serveur(adr_s, PORTS, h) ; -- adr_s = h.addrsendto(sock, "bonjour, serveur !! ", 20, 0, &adr_s,sizeof(adr_s));close(sock);
}
Programmation réseau● Interface socket : Communication en TCP
Programmation réseau● Interface socket : Communication en TCP
Programmation réseau● Interface socket : Communication en TCP
● int listen (sock, nb);– int sock; -- socket d'écoute– int nb; -- connexions pendantes max
● int accept (sock, p_adr, p_lgadr); -- retourne un descripteur socket de service– int sock; -- socket d'écoute du serveur– struct sockaddr_in *p_addr; -- @ socket connectée client– int *p_lgadr; -- taille de l'adresse
● int connect (sock, p_adr, lgadr);– int sock; -- socket client– struct sockaddr_in *p_addr; -- @ socket du serveur avec lequel s'établit la connexion
– int lgadr; -- taille de l'adresse
Programmation réseau● Interface socket : Communication en TCP
● int write (sock, msg, lg);– int sock; -- socket locale– char *msg; -- @ mémoire de la zone contenant le message– int lg; -- taille du message en octets
● int read (sock, msg, lg);– int sock; -- socket locale– char *msg; -- @ mémoire de la zone où recevoir le message– int lg; -- taille du message en octets
Programmation réseau● Interface socket : Communication en TCP
Programmation réseau● Interface socket : Communication en TCP
Programmation réseau● Interface socket : Communication en TCP#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#define PORTS 2058Main() { // SERVEUR
int namelen, sock, nsock, lg, n; char buf[20];struct sockaddr_in adr_s, adr_c;sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);/* Création socket */construit_adresse_locale(adr_s, PORTS) ; --adr_s = INADDR_ANYbind(sock, &adr_s, sizeof(adr_s)); /* Attachement socket */listen(sock,5);/* Boucle d'acceptation d'une connexion */while (TRUE) { /* Attente de question sur la socket */
lg = sizeof (adr_c);nsock = accept(sock, &adr_c, &lg);pid = fork();if (pid == 0) {
close (sock);read(nsock, buf, 20);close (nsock);exit();
} } }
Programmation réseau● Interface socket : Communication en TCP#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#define PORTS 2058main() { // CLIENT
struct hostent *h; int sock;struct sockaddr_in adr_s,adr_c;char buf[20];
/* Création socket */sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
/* Attachement socket */construit_adresse_locale (adr_c, 0) ; -- adr_c = INADDR_ANYbind(sock, &adr_c, sizeof(adr_c));/* Construction adresse du serveur */h=gethostbyname("fermi.cnam.fr");construit_adresse_serveur(adr_s, PORTS, h) ; -- adr_s = h.addrconnect(sock, &adr_s, sizeof(adr_s));write(sock, "bonjour, serveur !! ", 20);close (sock);
}
Exemple de construction :bzero(&adr_c,sizeof(adr_c));adr_c.sin_family=AF_INET;adr_c.sin_port=htons(PORT);adr_c.sin_addr.s_addr=INADDR_ANY;
Programmation réseau● Appels de procédures à distance (RPC)
● C'est un mécanisme général de communication entre processus dans les systèmes répartis.
● Permettre à un processus de réaliser, au cours de son exécution, un appel de procédure avec ses paramètres et valeurs de retour éventuels, dont l'exécution a lieu sur une autre machine.
● Protocole défini chez Sun Microsystems, à la base de l'implantation du système de fichiers répartis sous Unix, le protocole NFS (Network File System).
● Ensemble de services s'appuyant sur l'interface des sockets ● Paradigme de l'appel de procédure● Remplace les primitives (ex : send et receive)
Programmation réseau● Appels de procédures à distance (RPC)
● Permettre l'appel de procédures à travers le réseau :– Modèle client / serveur– Transparence : comme en local– Notion de souche/ subrogé (stub) client et serveur
Programmation réseau● Appels de procédures à distance (RPC)
● Etapes d'un appel d'une procédure Proc(x,y) à travers le réseau :– La souche client intercepte l'appel de procédure local, et transforme
la requête émise sur le réseau vers le serveur. Il y a un assemblage (ou marshalling, ou serialization) des paramètres x et y ;
– Le noyau client transmet sur le réseau (send) ;– La souche serveur désassemble les paramètres, et appelle
effectivement la procédure souhaitée ;– La procédure Proc(x,y) s'exécute et retourne le résultat à la
souche serveur ;– La souche serveur assemble la réponse ;– Le noyau serveur transmet la réponse sur le réseau ;– La souche client réceptionne, désassemble le résultat, et le retourne
au client en tant que « retour d'appel de procédure locale ».
Programmation réseau● Appels de procédures à distance (RPC)
● Etapes d'un appel d'une procédure Proc(x,y) à travers le réseau :
Programmation réseau● Appels de procédures à distance (RPC)
● Les difficultés rencontrées :– Passage des paramètres
● Comment faire pour les pointeurs ?– Gestion des pannes
● De réseaux● Du client● Du serveur
– Localisation des services● Serveur de désignation
Programmation réseau● Appels de procédures à distance (RPC)
● Problème du passage des paramètres
net
net
Programmation réseau● Appels de procédures à distance (RPC)
● Problème des pannes de réseau : les services idempotents
Programmation réseau● Appels de procédures à distance (RPC)
● Problème des pannes de réseau : les services idempotents– On réémet la demande à expiration d'un timer, mais le service a pu
être exécuté !– Exemples :
● Lecture des 1 024 premiers octets d'un fichier● Service bancaire : transférer 3 000 euros sur le compte du
percepteur– Solution :
● Placer un numéro de séquence sur les opérations. ● Le serveur refuse de refaire deux fois de suite une demande de
service portant un même numéro de séquence.
Programmation réseau● Appels de procédures à distance (RPC)
● Problème des pannes du serveur
Programmation réseau● Appels de procédures à distance (RPC)
● Problème des pannes du serveur
● Exécution au moins une fois : la nouvelle demande du client est rééxécutée● Exécution au plus une fois : la nouvelle demande du client est rejetée
Programmation réseau● Interface RPC via les sockets
● int rpc_call (char *host, // Name of server hostu_long prognum, // Server program numberu_long versnum, // Server version numberxdrproc_t inproc, // XDR filter to encode argchar *in, // Pointer to argumentxdr_proc_t outproc, // Filter to decode resultchar *out, // Address to store resultchar *nettype); // For transport selection
● bool_t rpc_reg(u_long prognum, // Server program numberu_long versnum, // Server version numberu_long procnum, // server procedure numberchar *procname, // Name of remote functionxdrproc_t inproc, // Filter to encode argxdrproc_t outproc, // Filter to decode resultchar *nettype); // For transport selection
Programmation réseau● Exemple RCP// Serveur#define RMTPROGNUM (u_long)0x3fffffffL#define RMTPROGVER (u_long)0x1#define RMTPROCNUM (u_long)0x1
#include <stdio.h>#include <rpc/rpc.h>
int *rmtproc(int *param) /* remote procedure */ { static int result; result = *param + *param; return(&result);}
main(){ int *rmtprog();
/* Register remote program with RPCBind */ if (rpc_reg(RMTPROGNUM, RMTPROGVER, RMTPROCNUM, rmtprog, xdr_int, xdr_int, "VISIBLE") == -1) { fprintf(stderr, "Could not Register\n"); exit(1); } svc_run(); exit(1);}
Programmation réseau● Exemple RCP// Client#define RMTPROGNUM (u_long)0x3fffffffL#define RMTPROGVER (u_long)0x1#define RMTPROCNUM (u_long)0x1
#include <stdio.h>#include <rpc/rpc.h>
main() { int inproc=100, outproc; enum clnt_stat rstat;
...
/* Service request to host RPCSERVER_HOST */ if (rstat = rpc_call("fermi.cnam.fr", RMTPROGNUM, RMTPROGVER, RMTPROCNUM, xdr_int, (char *)&inproc, xdr_int, (char *)&outproc, "VISIBLE") != RPC_SUCCESS){ fprintf(stderr,"rpc_call() failed\n"); exit(1); } ...}