Remote Procedure Call
Transcription
Remote Procedure Call
Remote Procedure Call z RPC permet de créer des programmes répartis en fournissant un mécanisme d’appel de procédures distantes z Communication Client/Serveur basé sur les sockets z Paradigme basé composantes (proécdures) A. Obaid © - Programmation des réseaux RPC 1 Objectifs z Distribution: – Répartir une application sur plusieurs machines z Transparence: – Appeler une procédure distante comme si elle était locale z Facilité de conception: – Transformer des applications locales en applications réparties z Indépendance du protocole de transport A. Obaid © - Programmation des réseaux RPC 2 1 1 Usage de RPC z Convertir une application développée localement en une application distribuée z Les procédures sont exécutées sur un site central: – – – – – Facilité d'adminsitration Facilité de mise à jour Respect des règles d'affaires Renforcer les règles d'intégrité pour les BD Centralisation des règles d'affaires RPC 3 A. Obaid © - Programmation des réseaux Modèle d'appel Appel RPC Appel local main() main(){{ ...... resultat resultat==somme(x,y); somme(x,y); ...... }} somme(int somme(intx,x,int inty)y){{ return(x+y); return(x+y); }} main() Client main(){{ ... ... resultat resultat==rpc(serveur,somme,(x,y); rpc(serveur,somme,(x,y); ... ... }} Réseau somme((x,y)) somme((x,y)){{ return(x+y); return(x+y); }} A. Obaid © - Programmation des réseaux Serveur RPC 4 2 2 Étapes d'un appel RPC Client Serveur Appel Retour Emballage des paramètres Retour Déballage du résultat P1 P2 Appel Emballage du résultat Déballage des paramètres Souche client Souche serveur Noyau Noyau Requête Réponse RPC 5 A. Obaid © - Programmation des réseaux Programmes RPC z Programme distant : – – – – z Unité s’exécutant sur une machine distante Identifié par un identifiant et un numéro de version Correspond à un serveur avec les procédures et les données Chaque procédure est identifiée par un numéro Programme local: – Interface avec l’utilisateur – Procédures locales Siaisie Client Réseau Insérer (insert) Serveur Recherche (select) BD Détruire (delete) A. Obaid © - Programmation des réseaux RPC 6 3 3 XDR z Bibliothèque de codage qui définit comment les données doivent être véhiculées sur le réseau z Permet d’échanger des données entre machines ayant des représentations internes différentes Client Serveur RPC XDR XDR TCP/UDP Réseau TCP/UDP RPC 7 A. Obaid © - Programmation des réseaux Échanges de paramètres n=somme(4,7) somme(struct param liste) { return (liste.i+liste.j) ; } XDR XDR somme 11 somme 4 4 7 7 A. Obaid © - Programmation des réseaux 11 RPC 8 4 4 Éléments de RPC z Composantes de l'architecture RPC: – – – – – – L’application cliente La souche du client Le serveur et les procédures La souche du serveur Le Portmapper L'API de communication A. Obaid © - Programmation des réseaux RPC 9 Élements de RPC z L’application cliente: – Traitement locaux: procédures locales, interfaces, saisies, … z La souche client: – Reçoit les ordres d'appel du client – Préparer pour un message d'appel (Marshalling) et l'envoie – Reçoit le message de réponse, le prépare (Unmarshalling) et le soumet au client A. Obaid © - Programmation des réseaux RPC 10 5 5 Élements de RPC z Le serveur et les procédures: – Reçoit les appels et les dirige vers les procédures – Récupère les résultats et les achemine vers la souche – Les procédures exécutent chacune une tâche z La souche serveur: – – – – Reçoit le message d'appel et le prépare (Unmarshalling) Le soumet au serveur. Récupère le résultat du serveur Prépare un message d'appel (Marshalling) et l'envoie RPC 11 A. Obaid © - Programmation des réseaux Le Portmapper z Programme qui résout les adresses (registry) – Il inscrit le serveur – Il répond aux requêtes de localisation (numéro de port) du serveur Port – Écoute au port 11 r Client eu er v mapper 11 Identité , port p de ête u q Re se pon Ré s de ort Requête client Port Réponse A. Obaid © - Programmation des réseaux Serveur RPC RPC 12 6 6 Identification RPC z Programmes: – Numéro de programme: selon un standard – Numéro de version: 1,2,3,… z Procédures: – Numéro de procédure: 1,2,3, … z Règle à suivre pour la numérotation: – Standard (ex. SUN) pour les programmes – Attribuer un nouveau numéro à chaque nouvelle version du même programme RPC 13 A. Obaid © - Programmation des réseaux La numérotation SUN Numéro Domaine 0x00000000-0x1FFFFFFF Réservé à SUN 0x20000000-0x3FFFFFFF Administration système 0x40000000-0x5FFFFFFF Pour les développeurs 0x60000000-0xFFFFFFFF Réservé Exemple: rstatd (Remote Host Status Monitoring) a le numéro 1000002. Il détecte les machines qui ont été réamorcées A. Obaid © - Programmation des réseaux RPC 14 7 7 Exemples de services RPC rpcbind 100000 Service d’enregistrement des serveurs RPC rstat 100001 Commande d’affichage de statistiques de performance d’un site ruserd 100002 Commande de listage d’informations sur les usagers d’un système distant nfs 100003 Service de fichiers NFS (Network File System) ypserv 100004 Service de répertoire de type pages jaunes de NIS (Network Information Service) de Sun mountd 100005 Service de montage des systèmes de fichiers pour NFS. A. Obaid © - Programmation des réseaux RPC 15 Exemple de déclaration RPC struct structpaire paire{ {int intx;x; int inty;y;};}; program programARITHMETIQUE ARITHMETIQUE{ { version versionARITHMETIQUE ARITHMETIQUE_VERSION _VERSION{ { int int somme somme(paire) (paire)==11; ; int int produit produit(paire) (paire)==22; ; int int puissance puissance(paire) (paire)==33; ; } }==11; ; } }==0x22222222 0x22222222; ; A. Obaid © - Programmation des réseaux RPC 16 8 8 rpcbind z C'est le programme démon qui implante un protmapper z Effectue les correspondances entre les numéros de programmes et de versions et leurs numéros de port z Un programme serveur RPC enregistre son numéro de programme et de version auprès du rpcbind A. Obaid © - Programmation des réseaux RPC 17 Programmation RCP z Trois niveaux: – Haut: Appels système (commandes) pour des commandes Unix éxécutées à distance – Intermédiaire: Accès à des fonctions élementaires de la librairie RPC – Bas: Programmation détaillée de RPC. Utilisée implicitement par le niveau intermédiaire A. Obaid © - Programmation des réseaux RPC 18 9 9 Programmation de haut niveau z Permet d’accéder aux fonctions : – rnusers() : nombre d’usagers actifs sur une station distante – havedisk() : si une station distante possède son propre disque – rstat() : informations sur le noyau d’un système distant – rwall() : envoie un messages aux terminaux de stations distantes z Utilise des démons spécifiques pour répondre A. Obaid © - Programmation des réseaux RPC 19 Exemple: Programmation de haut niveau #include #include<rpc/rpc.h> <rpc/rpc.h> #include #include<rpcsvc/rusers.h> <rpcsvc/rusers.h> main(int main(intargc, argc,char char **argv) **argv) { { int nombre ; if (argc int nombre ; if (argc!=!=2) 2) exit(1) exit(1); ; ifif((nombre ((nombre==rnusers(argv[1])) rnusers(argv[1]))<<0) 0) exit(-1) exit(-1); ; printf("On printf("Onaa%d %dusagers usagerssur sur%s\n", %s\n",nombre, nombre,argv[1])) argv[1])); ; exit(0); exit(0); }} A. Obaid © - Programmation des réseaux RPC 20 10 10 Programmation de niveau intermédiaire z Utilise des fonctions spécifiques: – registerrpc() : enregistre une procédure auprès du portmapper – svc_run(): attend l’arrivée d’un appel du service RPC – callrpc(): exécute un appel à distance A. Obaid © - Programmation des réseaux RPC 21 Fonctions de niveau intermédiaire #include #include<rpc/rpc.h> <rpc/rpc.h> registerrpc(int registerrpc(int prognum, prognum,int int versnum, versnum,int int procnum, procnum, char char*(*procname), *(*procname),xdrproc_t xdrproc_tinproc, inproc,xdrproc_t xdrproc_toutproc) outproc) #include #include<rpc/rpc.h> <rpc/rpc.h> void voidsvc_run svc_run(void); (void); #include #include<rpc/rpc.h> <rpc/rpc.h> callrpc callrpc( (char char*host, *host,int int prognum, prognum,int intversnum, versnum,int int procnum, procnum, xdrproc_t xdrproc_tinproc, inproc, char char*in, *in,xdrproc_t xdrproc_toutproc, outproc,char char*out) *out) A. Obaid © - Programmation des réseaux RPC 22 11 11 Exemple: Programmation de niveau intermédiaire - Serveur #include #include<rpc/rpc.h> <rpc/rpc.h> #include #include<rpc/xdr.h> <rpc/xdr.h> #define #definePROGRAMME PROGRAMME #define #defineVERSION VERSION #define #defineNUM_PROC_P1 NUM_PROC_P1 #define NUM_PROC_P2 #define NUM_PROC_P2 20000003 20000003 11 11 22 char char*P1(){ *P1(){static staticint intres; res; res=5; res=5;return return((char ((char*)&res); *)&res);} } char char*P2(){ *P2(){static staticint intres; res; res=10; res=10; return return((char ((char*)&res); *)&res);} } main() main(){ { printf("Programme: printf("Programme:%u %u- -Version: Version:%u %u- -Procedure: Procedure:%u\n", %u\n", PROGRAMME, PROGRAMME,VERSION VERSION, ,NUM_PROC_P1); NUM_PROC_P1); registerrpc(PROGRAMME, registerrpc(PROGRAMME,VERSION VERSION, ,NUM_PROC_P1, NUM_PROC_P1,P1, P1,xdr_void, xdr_void,xdr_u_long); xdr_u_long); printf("Programme: printf("Programme:%u %u- -Version: Version:%u %u- -Procedure: Procedure:%u\n", %u\n", PROGRAMME, VERSION , NUM_PROC_P2); PROGRAMME, VERSION , NUM_PROC_P2); registerrpc(PROGRAMME, registerrpc(PROGRAMME,VERSION VERSION, ,NUM_PROC_P2, NUM_PROC_P2,P2, P2,xdr_void, xdr_void,xdr_u_long); xdr_u_long); svc_run(); svc_run(); exit(1); exit(1); }} A. Obaid © - Programmation des réseaux RPC 23 Exemple: Programmation de niveau intermédiaire - Client #include #include<stdio.h> <stdio.h> #include #include<rpc/rpc.h> <rpc/rpc.h> #include #include<rpc/xdr.h> <rpc/xdr.h> #define 20000003 #definePROGRAMME PROGRAMME 20000003 #define 11 #defineVERSION VERSION #define 11 #defineNUM_PROC_P1 NUM_PROC_P1 #define 22 #defineNUM_PROC_P2 NUM_PROC_P2 main(int main(intargc, argc,char char*argv[]) *argv[]){ { unsigned unsignedlong longp1, p1,p2; p2; int intstat; stat; printf("Machine printf("Machine: :%s %s\n", \n",argv[1]); argv[1]); ifif(stat (stat==callrpc(argv[1], callrpc(argv[1],PROGRAMME, PROGRAMME,VERSION, VERSION, NUM_PROC_P1, NUM_PROC_P1, xdr_void, xdr_void,0,0,xdr_u_long, xdr_u_long,&p1) &p1)!=!=0) 0) exit(1); exit(1); printf("L'appel printf("L'appelde deP1 P1retourne retourne: :%d %d\n", \n",p1); p1); ifif(stat (stat==callrpc(argv[1], callrpc(argv[1],PROGRAMME, PROGRAMME,VERSION, VERSION, NUM_PROC_P2, NUM_PROC_P2, xdr_void, 0, xdr_u_long, &p2) != 0) xdr_void, 0, xdr_u_long, &p2) != 0) exit(2); exit(2); printf("L'appel printf("L'appelde deP2 P2retourne retourne: :%d %d\n", \n",p2); p2); exit(0); exit(0); }} A. Obaid © - Programmation des réseaux RPC 24 12 12 rpcgen z Un outil qui permet de générer des applications RPC z En entrée, il accepte une description en RPCL (RPC Language) et génère des fichiers en C: – – – – – Les souches client et serveur Un gabarit du serveur Un gabarit du client Les procédures XDR Des fichiers d'en-tête A. Obaid © - Programmation des réseaux RPC 25 RPCL z C'est langage de description d'interfaces: – Interface Definition Language (IDL) z Permet de définir un contrat du service avec ses clients potentiels z Utilisé pour générer automatiquement des souches et des gabarits d'implantation A. Obaid © - Programmation des réseaux RPC 26 13 13 Composantes d'une application RPC Architecture en local: Proc. A Proc. B Proc. A1 Proc. A2 Souche B1 Souche B2 Architecture en RPC: Proc. A Souche B Souche B Proc. B Souche - Dispatcher Souche B1 Souche B2 Proc. B1 Proc. B2 A. Obaid © - Programmation des réseaux RPC 27 Utilisation de rpcgen z On suit les étapes suivantes: – Écrire une spécification RPCL (ex. P.x) – Précompiler avec rpcgen. Ceci génère : Les souches: P_clnt.c et P_svc.c Les fichiers XDR et les en-têtes: P_xdr.c, et P_.h – – – – Autres dans certains environnements Écrire le programme client Écrire le programme serveur Compiler le client avec P_clnt.c et P _xdr.c Compiler le serveur avec P_svc.c et P_xdr.c A. Obaid © - Programmation des réseaux RPC 28 14 14 Utilisation de rpcgen Proc. A Communication Serveur Souche: P_svc.x Interface Client Interface Serveur Souche: P_clnt.c Communication Client Proc. B RPC 29 A. Obaid © - Programmation des réseaux Utilisation de rpcgen Application P_clnt.c P.x rpcgen CC Client CC Serveur P.h P_xdr.c P_svc.c Procédures A. Obaid © - Programmation des réseaux RPC 30 15 15 Conception d'applications RPC z Garder locales les procédures – De saisie de données et de présentation (GUI, …) – De manipulation de données locales – De gestion locales z Distribuer les procédures: – Auprès de données distantes qu'elles manipulent – Que l'on veut centraliser pour imposer des règles d'affaires – De gestion centralisée RPC 31 A. Obaid © - Programmation des réseaux Exemple - Application RPC main Lire Init InsereM DetruitM ChercheM Prédures de manipulation d'un dictionnaire: Lire: Lit une commande à exécuter Init: Initialise le dictionnaire InsereM: Insère un mot dans le dictionnaire DetruitM: Détruit un mot du dictionnaire ChercheM: Cherche un mot dans le dictionnaire A. Obaid © - Programmation des réseaux RPC 32 16 16 Exemple - Application RPC Init main InsereM DetruitM Lire ChercheM Dictionnaire, Variables,... Serveur Client RPC 33 A. Obaid © - Programmation des réseaux La commande rpcinfo z rpcfinfo permet de manipuler les services RPC sur un serveur. rpcinfo rpcinfo-s. -s. program program 100000 100000 100029 100029 100078 100078 100087 100087 100011 100011 100020 100020 version(s) service version(s)netid(s) netid(s) service 2,3,4 udp,tcp,ticlts,ticotsord,ticots 2,3,4 udp,tcp,ticlts,ticotsord,ticots rpcbind rpcbind 2,1 ticots,ticotsord,ticlts keyserv 2,1 ticots,ticotsord,ticlts keyserv 44 ticots,ticotsord,ticlts kerbd ticots,ticotsord,ticlts kerbd 10 udp admind 10 udp admind 11 ticlts,udp rquotad ticlts,udp rquotad 33 ticots,ticotsord,ticlts,tcp,udp ticots,ticotsord,ticlts,tcp,udp llockmgr llockmgr … … 1342177280 tcp -1342177280 1,2 1,2 tcp 823202065 ticots,ticotsord,ticlts,tcp,udp 823202065 11 ticots,ticotsord,ticlts,tcp,udp - - owner owner superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser 461 461 520 520 rpcinfo rpcinfo-d -d823202065 823202065 11 Détruit Détruit leleservice service 823202065 823202065 Version Version11 A. Obaid © - Programmation des réseaux RPC 34 17 17 Types de serveurs z Deux types de serveurs : – Avec état (statefull): Le serveur conserve des informations sur les requêtes des clients – Sans état (stateless): Aucune information sur les rquêtes des clients n’est mémorisée Le client pourrait s’en occuper A. Obaid © - Programmation des réseaux RPC 35 Types de procédures z Deux types d’opérations RPC: – Idempotente: L' opération peut se répéter sans effet cumulatif X=X op X Exemple: certaines lectures de fichier – Non idempotente: La réptition de l'opération a un effet cumulatif Exemple: un transfert de fonds A. Obaid © - Programmation des réseaux RPC 36 18 18 Exemple - Opération non idempotente z Les opérations d'écriture ne sont pas idempotentes: int write_file (int fd, char *buf, int nbytes) { put_block(fd,nbytes,buf); } serveur client f_h put_block() fd fichier A. Obaid © - Programmation des réseaux RPC 37 Sémantique des appels RPC z Erreurs d'appels RPC: – Requête perdue: Refaire l'appel – Réponse perdue: Refaire l'appel. Effet indésirable Solution: Numéroter les requêtes (information d'état). – Le serveur est tombé: z On perd les informations d'état Solutions: – Requêtes idempotentes – Serveurs sans état A. Obaid © - Programmation des réseaux RPC 38 19 19 Exemple- Requête idempotente int intput_block(int put_block(intfile, file,int intoffset, offset,int intcount, count,char char *data) *data){ { int intreturn_code return_code==0;0; ifif(lseek(file, (lseek(file,offset, offset,SEEK_SET) SEEK_SET)== ==-1) -1) return_code= return_code=-1; -1; else else return_code return_code==write(file,data,count); write(file,data,count); return (return_code); return (return_code); }} static staticoffset=0; offset=0; int intwrite_file write_file(int (intfd, fd,char char*buf, *buf,int intnbytes) nbytes) { { int nbytes; int nbytes; ifif(nbytes (nbytes==put_block(fd,nbytes,buf) put_block(fd,nbytes,buf)!=!=-1 -1) ) offset offset+=nbytes; +=nbytes; return return(nbytes); (nbytes); }} A. Obaid © - Programmation des réseaux RPC 39 Exemple: Fichier rand.x z Un application qui offre des procédures de génération de nombres aléatoires: – INITIALISE() pour initialiser un germe de génération – GENERE_ALEAT() qui génère un nombre aléatoire program programRAND_PROG RAND_PROG{{ version versionRAND_VERS RAND_VERS{{ void void INITIALISE(long) INITIALISE(long)=1; =1; double double GENERE_ALEAT(void) GENERE_ALEAT(void)=2 =2; ; }}==1; 1; }}==0x31111111; 0x31111111; A. Obaid © - Programmation des réseaux RPC 40 20 20 Exemple: Fichier rand.h Généré par rpcgen #include #include<rpc/rpc.h> <rpc/rpc.h> #define #define RAND_PROG RAND_PROG((unsigned ((unsignedlong)(0x31111111)) long)(0x31111111)) #define RAND_VERS ((unsigned #define RAND_VERS ((unsignedlong)(1)) long)(1)) #define #define INITIALISE INITIALISE((unsigned ((unsignedlong)(1)) long)(1)) extern extern void void**initialise_1(); initialise_1(); #define #define GENERE_ALEAT GENERE_ALEAT((unsigned ((unsignedlong)(2)) long)(2)) extern double * genere_aleat_1(); extern double * genere_aleat_1(); extern externint intrand_prog_1_freeresult(); rand_prog_1_freeresult(); A. Obaid © - Programmation des réseaux RPC 41 Exemple: Fichier rand_client.c Gabarit de du client. Généré (ou pas) par rpcgen. À compléter. #include #include"rand.h" "rand.h" void void rand_prog_1(host) rand_prog_1(host) char char*host; *host; {{ CLIENT CLIENT*clnt; *clnt; void void *result_1; *result_1; long long initialise_1_arg; initialise_1_arg; double double *result_2; *result_2; char char** genere_aleat_1_arg; genere_aleat_1_arg; }} clnt clnt==clnt_create(host, clnt_create(host,RAND_PROG, RAND_PROG,RAND_VERS, RAND_VERS,"netpath"); "netpath"); ifif(clnt (clnt== ==(CLIENT (CLIENT*)*)NULL) NULL){ { clnt_pcreateerror(host); clnt_pcreateerror(host); exit(1); exit(1); A. Obaid © - Programmation des réseaux RPC 42 21 21 Exemple: Fichier rand_client.c result_1 result_1==initialise_1(&initialise_1_arg, initialise_1(&initialise_1_arg,clnt); clnt); ifif(result_1 == (result_1 ==(void (void*)*)NULL) NULL){ { clnt_perror(clnt, clnt_perror(clnt,"call "callfailed"); failed");} } result_2 result_2==genere_aleat_1((void genere_aleat_1((void*)&genere_aleat_1_arg, *)&genere_aleat_1_arg,clnt); clnt); ifif(result_2 (result_2== ==(double (double*)*)NULL) NULL){ { clnt_perror(clnt, clnt_perror(clnt,"call "callfailed"); failed"); }} clnt_destroy(clnt); clnt_destroy(clnt); }} main(argc, main(argc,argv) argv) int intargc; argc; char char*argv[]; *argv[]; { {char char*host; *host; ifif(argc (argc<<2) 2){ { printf("usage: printf("usage: %s %sserver_host\n", server_host\n",argv[0]); argv[0]); exit(1); exit(1);} } host host==argv[1]; argv[1]; rand_prog_1(host); rand_prog_1(host); }} A. Obaid © - Programmation des réseaux RPC 43 Exemple: Fichier rand_clnt.c Souche du client. Généré par rpcgen. #include #include"rand.h" "rand.h" void void**initialise_1(long initialise_1(long*argp, *argp, CLIENT CLIENT*clnt) *clnt) {{ static staticchar charclnt_res; clnt_res; memset((char memset((char*)&clnt_res, *)&clnt_res,0,0,sizeof sizeof(clnt_res)); (clnt_res)); ifif(clnt_call(clnt, (clnt_call(clnt,INITIALISE, INITIALISE, (xdrproc_t) (xdrproc_t)xdr_long, xdr_long,(caddr_t) (caddr_t)argp, argp, (xdrproc_t) (xdrproc_t)xdr_void, xdr_void,(caddr_t) (caddr_t)&clnt_res, &clnt_res, TIMEOUT) TIMEOUT)!=!=RPC_SUCCESS) RPC_SUCCESS){ { return return(NULL); (NULL); }} return return((void ((void*)&clnt_res); *)&clnt_res); }} double double*genere_aleat_1(void *genere_aleat_1(void*argp, *argp,CLIENT CLIENT*clnt) *clnt){{… …}} … … A. Obaid © - Programmation des réseaux RPC 44 22 22 Exemple: Fichier rand_server.c Gabarit du serveur. Généré ou pas par rpcgen. A compléter. #include #include"rand.h" "rand.h" void void*initialise_1(argp, *initialise_1(argp,rqstp) rqstp) long long*argp; *argp; struct structsvc_req svc_req*rqstp; *rqstp; {{ static staticchar char**result; result; /*/* Ajouter Ajouterlelecode codede delalaprocedure procedureici ici*/*/ return((void return((void*)*)&result); &result); }} double double*genere_aleat_1(argp, *genere_aleat_1(argp,rqstp) rqstp) void void*argp; *argp; struct structsvc_req svc_req*rqstp; *rqstp; {{ static staticdouble double result; result; /*/* Ajouter Ajouterlelecode codede delalaprocedure procedureici ici*/*/ return return(&result); (&result); }} A. Obaid © - Programmation des réseaux RPC 45 Exemple: Fichier rand_svc.c Souche du serveur. Généré par rpcgen. static staticvoid voidrand_prog_1(struct rand_prog_1(structsvc_req svc_req*rqstp, *rqstp,register registerSVCXPRT SVCXPRT*transp) *transp){ { … … switch switch(rqstp->rq_proc) (rqstp->rq_proc){ { … … case caseINITIALISE: INITIALISE: xdr_argument xdr_argument==xdr_long; xdr_long; xdr_result xdr_result==xdr_void; xdr_void; local local==(char (char*(*)()) *(*)())initialise_1; initialise_1; break; break; case caseGENERE_ALEAT: GENERE_ALEAT: xdr_argument xdr_argument==xdr_void; xdr_void; xdr_result xdr_result==xdr_double; xdr_double; local local==(char (char*(*)()) *(*)())genere_aleat_1; genere_aleat_1; break; break; … … }} A. Obaid © - Programmation des réseaux RPC 46 23 23 Exemple: Fichier rand_svc.c result result==(*local)(&argument, (*local)(&argument,rqstp); rqstp); svc_sendreply(transp, svc_sendreply(transp,xdr_result, xdr_result,result); result); … … main() main() {{ … … svc_create(rand_prog_1, svc_create(rand_prog_1,RAND_PROG, RAND_PROG,RAND_VERS, RAND_VERS,"netpath"); "netpath"); … … svc_run(); svc_run(); }} A. Obaid © - Programmation des réseaux RPC 47 24 24