Appel de procédure distante

Slides:



Advertisements
Présentations similaires
Mais vous comprenez qu’il s’agit d’une « tromperie ».
Advertisements

Le Nom L’adjectif Le verbe Objectif: Orthogram
ORTHOGRAM PM 3 ou 4 Ecrire: « a » ou « à » Référentiel page 6
Premier programme en C :
Licence pro MPCQ : Cours
A RECUPERER EN ENTRANT Le polycopié de Caml Partie 1
Rappels C.
Distance inter-locuteur
Les numéros
Les identités remarquables
Cours MIAGE « Architectures Orientées Services » Henry Boccon-Gibod 1 Architectures Orientées Services Composants de Service Exemple pratique de développement.
Cours n°2M2. IST-IE (S. Sidhom) UE 303 Promo. M2 IST-IE 2005/06 Conception dun système d'information multimédia Architecture trois-tiers : PHP/MySQL &
Architecture de réseaux
C.
Algorithme et structure de données
LICENCE MIAGE Introduction Programmation Orientée Objet JAVA philippe
LES TRIANGLES 1. Définitions 2. Constructions 3. Propriétés.

Structures et unions types énumérés Qu'est-ce qu'une structure
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
Common Gateway Interface
ALGORITHMES RECURSIFS
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Olivier DERUELLE Erwan FOUYER Maxime JOUIN Rodolphe LOUE
Synchronisation et communication entre processus
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
La fonction alloue un bloc de taille size. Il faut indiquer la taille du bloc que lon veut allouer. Le premier exemple: #include void main()
Titre : Implémentation des éléments finis sous Matlab
TRAITEMENT DE STRUCTURES
Projet poker 1/56. Introduction Présentation de léquipe Cadre du projet Enjeux Choix du sujet 2.
Introduction à la programmation (Java)
F Copyright © Oracle Corporation, Tous droits réservés. Créer des programmes avec Procedure Builder.
LES NOMBRES PREMIERS ET COMPOSÉS
Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert?
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Représentation des systèmes dynamiques dans l’espace d’état
DUMP GAUCHE INTERFERENCES AVEC BOITIERS IFS D.G. – Le – 1/56.
Programmation concurrente
IFT 6800 Atelier en Technologies d’information
Année universitaire Réalisé par: Dr. Aymen Ayari Cours Réseaux étendus LATRI 3 1.
Chapitre 9 Les sous-programmes.
8PRO100 Éléments de programmation Les types composés.
COURS DE PROGRAMMATION ORIENTEE OBJET :
COURS DE PROGRAMMATION ORIENTEE OBJET :
MAGIE Réalisé par Mons. RITTER J-P Le 24 octobre 2004.
1 INETOP
Christine Bonnet SOURCES : « Samples » dOracle, « Oracle 8 » R. Chapuis PRO*C – C ++
Structures de données IFT-2000 Abder Alikacem Semaine 12 (2 ième partie) Les B-arbres Département d’informatique et de génie logiciel Édition septembre.
P.A. MARQUES S.A.S Z.I. de la Moussière F DROUE Tél.: + 33 (0) Fax + 33 (0)
MAGIE Réalisé par Mons. RITTER J-P Le 24 octobre 2004.
Structures des données
1/65 微距摄影 美丽的微距摄影 Encore une belle leçon de Macrophotographies venant du Soleil Levant Louis.
2.1 - Historique Chapitre 2 : Introduction au langage C++
Nom:____________ Prénom: ___________
Ch. PAUL - Piles et Files à l'aide de listes chainées
4 Introduction des objets. Les chaînes et tableaux
LES PILES ET FILES.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
Notions de pointeurs en C
La notion de type revisitée en POO
et quelques rappels sur certains éléments du langage C
Les adresses des fonctions
Les sockets.
Les types composés Les enregistrements.
PHP 6° PARTIE : LES SESSIONS 1.Introduction 2.Identificateur de session 3.Variables de session 4.Client / Serveur 5.Principe 6.Ouverture de session 7.Enregistrement.
Classe 1 CSI2572 Autres modificateurs de déclaration de variables: & volatile & register & static & auto & extern & const volatile Indique au compilateur.
Les RPC remote procedure call
1 Communications dans les systèmes distribués. 2 On distingue plusieurs niveaux d’abstractions 1. Bas Niveaux : Sockets 2. Niveau intermédiaire : transparence.
Langage de Programmation Orientée Objet : C++
Informatique 2A Langage C 5ème séance. Déroulement de la séance 5 1 ère partie Étude des chaînes de caractères 2 ème partie Les structures 3.
Transcription de la présentation:

Appel de procédure distante Le RPC Appel de procédure distante

Plan Introduction (suite) XDR Mise en oeuvre du RPC RPCGEN

Mécanisme Programme Client Appel de Procédure distante Prise en compte de la demande (Processus démon) Réveil du serveur Exécution du service Message de réponse

Traitement des défaillances 3 entités sujettes à défaillance site client, site serveur et système de communication Nécessité de définir le comportement de l’appel de procédure à distance dans les différentes hypothèses de défaillance sémantique de l’appel de procédure à distance Réaliser les mécanismes nécessaires au traitement des défaillances

Exemples de défaillances Impossible de contacter le serveur Perte d’un message client -> serveur appel ou acquittement Perte d’un message serveur -> client retour, acquittement Défaillance du serveur au cours de l’appel À quel moment exactement ? Défaillance du client entre l’appel et le retour

Sémantiques de l’appel de procédure à distance (défaillance du serveur) Exécution incertaine (may be semantics [SPECTOR 82] un seul message d’appel en présence de pannes procédure exécutée 0, 1 fois Exécution au moins une fois (at least once semantics [BACON 87] en présence de panne au moins une fois si le client reçoit message de RETOUR

Sémantiques du RPC Exécution au moins une fois (suite) Protocole : délai de garde sur site client retransmission du message d ’APPEL abandon de l’appel par le site client à l’issue d’un nombre prédéfini de retransmissions sans message de RETOUR Convient aux procédures idempotentes

Sémantiques du RPC Exécution au moins une fois et retour du résultat de la dernière exécution (last of many semantics) [LAMPSON 81] Protocole retransmission du message APPEL numérotation en séquence des messages APPEL correspondants à un même RPC conservation du dernier message APPEL envoyé

Sémantiques du RPC Serveur conserve le numéro de séquence du dernier message APPEL reçu et chaque message APPEL donnant lieu à une exécution Serveur n’exécute un APPEL que si son numéro de séquence est supérieur à ceux reçus antérieurement Client élimine tous les messages RETOUR ne correspondant pas au dernier message APPEL

Sémantiques du RPC Exécution au plus une fois (at most once semantics) [LISKOV 87, Argus] motivée par la construction d’applications distribuées très fiables (système bancaire) fondée sur des actions atomiques (tout ou rien) redondance mise en œuvre coûteuse procédure exécutée 0 ou 1 fois en cas de défaillance

Le problème des orphelins (défaillance du client) Cause des orphelins retransmission du message APPEL peut provoquer plusieurs exécutions de la procédure appelée, toutes sauf une sont des orphelins exception ou défaillance du client quand le client cesse d’attendre le message RETOUR, l ’exécution de la procédure sur le serveur est un orphelin Orphelins indésirables peuvent interférer avec les exécutions valides consomment des ressources du système augmentation des conflits, baisse des performances

Traitement des orphelins Prévention Elimination Récupération

Traitement des orphelins Prévention numérotation des messages d ’APPEL avec un identificateur unique (uid) associé à l’appel de procédure à distance serveur écarte tous les messages redondants conservation du résultat et de l’uid d’un appel en mémoire stable pour faire face à la défaillance du serveur

Traitement des orphelins Elimination à l’initiative du site client élimination lors d’une reprise après panne du site client contacte les sites ayant donné lieu à des appels notifie l’appelant à l ’échéance d’un délai d’exécution dans les systèmes où les horloges des sites sont synchronisées un site élimine un processus qui exécute un appel au bout d ’un temps fixé à l’initiative du site serveur lorsqu’un site est détecté en panne, les appels qu’il a initialisés sont éliminés

Traitement des orphelins Récupération suppose l’existence d ’un mécanisme de reprise après panne des processus conservation en mémoire stable des numéros de séquence des messages d’APPEL et de RETOUR conservation des résultats de l’appel en mémoire stable sur le serveur

RPC et Couches OSI (Open Systems Interconnection ftp, rsh, rlogin,… NFS, NIS Application Présentation XDR RPC Session Transport TCP UDP Réseau IP Liaison Physique

Réalisation d’un appel de procédure à distance Site appelé (serveur) Site appelant (client) Programme appelant Talon client Talon serveur Programme appelé appel emballage déballage Gestion processus <attente> Exécution procédure retour déballage emballage message Envoi paramètres Réception paramètres Système de communication Envoi résultats Réception résultats message

Le protocole doit permettre : Identification de la procédure Authentification de la demande   Identification : §       regroupement des procédures en un programme §       Numéro de Programme, Numéro de version Numéro de procédure Authentification : possibilité pour un client de s ’identifier auprès d ’un serveur sécurité d’accès Echange d ’informations (paramètres ou résultats ) utilisent la représentation XDR (External data representation, Sun Microsystems) Représentation standard, indépendante de la structure de physique de la machine, échangeable entre machines de types différentes

Deux outils de génération RPC Sun RPC, (RFC1057 pour la v2) DCE de l ’OSF Sun RPC 2 versions • une version bâtie sur l ’API Socket - Fonctionnement en mode connecté TCP - Fonctionnement en mode non connecté UDP • une version bâtie sur l ’API TLI - appelé TI-RPC

3 niveaux de mise en œuvre des RPC Sun Bas niveau Niveau intérmediare Haut niveau ( RPCgen )

XDR Généralités Couche de présentation des données XDR • Marshaling/Unmarshaling des paramètres et résultat XDR (RFC1014) • Proposé par Sun • Couche de présentation des données • format pivot de représentation des données de types primitifs quelque soit Äl ’architecture (Little Endian/Big Endian, IEEE, … ) Äle langage (ordre ligne/colonne dans les tableaux C et les tableaux Fortran) Äou le système (ASCII, IBM ’ECDCII, ...)

Représentation XDR Big-Endian pour les entiers Alignement multiple de 4 Repésentation IEEE pour les flottants La librairie XDR Contrairement au sockets, les fonctions XDR ne sont pas des appels système mais des fonctions de librairie externe au système. Les fichiers d'include #include <rpc/types.h> #include <rpc/xdr.h>

Fonctions de manipulation de flot XDR Les données converties du format machine dans leur représentation XDR sont placées dans un flot XDR. Inversement, les données sont lues dans un flot XDR et transformées de leur représentation XDR vers la représentation machine Constantes et types prédéfinis bool_t -> FALSE, TRUE : booléen xdr_op -> XDR_ENCODE, XDR_DECODE, XDR_FREE : type du flot XDR : structure opaque de description de flot (<=>FILE)

Les filtres XDR Un filtre a trois fonctionnalités. Il permet l'encodage, le décodage mais également la libération de la mémoire qui a pu être allouée par le filtre. Tous les filtres renvoie TRUE en cas de réussite et FALSE en cas d'échec! Type Filtre char xdr_char() short xdr_short() … … … float xdr_float() double xdr_double() void xdr_void() enum xdr_enum()

Les deux arguments d'un filtre sont de même type en encodage et en décodage. boolt xdr_type (XDR*pt_xdr,type*pt); Paramètres : 1.     pt_xdr : pointeur sur le flot XDR en encodage ou décodage 2.     pt : pointeur sur zone contenant valeur à encoder ou zone réservée pour recevoir la valeur décodée Retour : 1. TRUE : en cas de succès FALSE : en cas d'échec

Encodage des booléens bool_t xdr_bool(XDR*pt_xdr, bool_t * pt);   Encodage de chaînes de caractères bool_t xdr_string (XDR*pt_xdr,char**pt,u_int taille_max); Paramètres : 1.     pt_xdr : pointeur de flot XDR 2.     pt : pointe sur le pointeur de la chaîne de caractères à encoder ou sur une zone mémoire contenant l'adresse de la zone réservé pour stocker la chaîne à décoder 3.     taille_max : taille maximale de la chaîne Il y a allocation de mémoire dynamique de mémoire pour stocker la chaîne si *pt est NULL en décodage, sinon erreur en encodage. -> xdr_wrapstring(XDR*pt_xdr,char**pt) appelle xdr_string avec taille_max=UINT_MAX

Encodage de suites d'octets bool_t xdr_opaque(XDR *pt_xdr, char*pt,int taille); Paramètres : 1.     pt_xdr : pointeur sur le flot XDR 2.     pt : pointeur sur suite d'octets à encoder ou sur la zone réservée pour stocker la suite d'octets à décoder 3.     taille : taille de la suite d'octets

bool_t xdr_bytes(XDR *pt_xdr,char**pt,u_int *pt_taille, u_int max); Paramètres : 1.     pt_xdr : pointeur sur le flot XDR 2.     pt : pointe sur le pointeur de la zone mémoire qui contient la suite d'octets à encoder ou sur la zone mémoire réservée pour contenir la suite d'octets à décoder. 3.     pt_taille : pointe sur la taille de la suite d'octets à encoder ou sur zone réservée contenant avant appel la taille de la zone réservée sous *pt et après appel la taille de la suite d'octets décodée. 4.     max : taille maximale de la suite d'octets à décoder Si *pt=NULL en décodage, il y a allocation dynamique de la mémoire nécessaire

Encodage de tableau bool_t xdr_vector(XDR*pt_xdr,void*pt,u_int taille,u_int taille_case,xdrproc_t xdr_type); Paramètres : 1.     pt_xdr : pointeur sur le flot XDR 2.     pt : pointeur sur le tableau 3.     taille : nombre de case du tableau 4.     taille_case : taille des éléments du tableau 5.     xdr_type : pointeur sur la fonction d'encodage et de décodage du type des éléments du tableau

bool_t xdr_array( XDR*pt_xdr, void**pt, u_int*taille, u_int max, u_int taille_case, xdr proc_t xdr_type); Paramètres : pt_xdr : pointe sur le flot XDR pt : pointe sur le pointeur de début du tableau à encodé ou sur la zone mémoire réservée pour contenir le tableau décodé taille : pointe sur le nombre de cases du tableau à encoder ou sur zone réservée contenant avant appel le nombre de case de la zone réservée sous *pt et après appel le nombre de cases effectivement utilisées. max : taille maximale de la zone à décoder taille_case, xdr_type : même chose que xdr_vector Allocation automatique de mémoire si *pt=NULL

Encodage des strucures Il n'y a pas de fonction prédéfinies pour l'encodage des structures. Exemple : struct structure { type1 ch1; type2 ch2; ... typen chn;}; bool_t xdr_structure(XDR * pt_xdr, struct structure* pt){ return(xdr_type1(pt_xdr,&(pt->ch1)) &&xdr_type2(pt_xdr,&(pt->ch2))&&...xdr_typen(pt_xdr,&(pt->chn)));

Encodage des unions bool_t xdr_union(XDR*pt_xdr,enum_t *disçvoid*union_pt,struct xdr_discrim * choices, xdr_proc_t defaultarm); Paramètres : pt_xdr : pointeur sur flot XDR disc : pointeur sur discriminant de l'union union_pt : pointeur sur l'union choices : tableau de pointeur de fonction de codage en fonction du discriminant defaultarm : pointeur de fonction de codage par défaut.

Encodage des pointeurs bool_t xdr_reference(XDR*pt_xdr,char**pt,u_int taille,xdrproc_t f); Permet d'encoder ou de décoder un pointeur et l'objet pointé Paramètres : 1.     pt_xdr : pointeur sur flot XDR 2.     pt : pointe sur le pointeur à encoder ou sur zone qui contiendra le pointeur décodé 3.     taille : taille de l'objet pointé 4.     f : fonction XDR du type de l'objet pointé Errreur si *pt=NULL en encodage Si *pt=NULL en décodage alloue la zone necessaire. bool_t xdr_pointer(XDR*pt_xdr,void**pt,u_int taille,xdrproct f); Mêmes paramètres que xdr_reference. Encode le pointeur NULL ce qui permet d'encoder les structures récursives.

Exemple : typedef struct maillon { int val; struct maillon *next; } liste; bool_t xdr_liste(XDR*pt_xdr,liste*pt_liste) { return (xdr_pointer (pt_xdr,&pt_liste->next,sizeof(liste),xdr_liste) &&xdr_int(pt_xdr,&pt_liste->val)); }

La gestion mémoire Certaines fonctions allouent de la mémoire dynamiquement au moyen de malloc() lors du décodage (xdr_array, xdr_bytes, xdr_pointer, xdr_reference, xdr_string, xdr_vector), il peut être utile de la libérer. void xdr_free (xdr_proc_t proc, void* objet); Paramètres : 1.     proc : fonction XDR de manipulation de l'objet à désallouer 2.     obj_pt : pointeur sur l'objet à désallouer

Exemple : char *string = NULL; XDR xdr; xdrstdio_create (&xdr, file, XDR_DECODE); xdr_string (&xdr, &string,20); xdr_free (xdr_string,& string);

Mécanisme de mise en œuvre

Client Serveur Portmap 2 Programme client 1 Programme serveur 3

1. Le programmeur serveur enregistre son N° de port, N° programme N° de version   2. Le programme client interroge le daemon Portmap et obtient le N° de port associé au programme serveur 3. Le programme client appelle le programme serveur 

Développement de service RPC Etapes : 1 Coté serveur -     Implémentation des fonctions - Choix du numéro de programme et de version -    Enregistrement des différents fonctions par le deamon portmap (registerrpc) Fonction d’enregistrement   int registerrpc(prog, version, proc, f, xdr_arg, xdr_res) La fonction registerrpc permet l’enregistrement chez le serveur de la procédure à appeler à distance.  prog : numéro du programme version : numéro de version proc : numéro de version f : nom de la procédure xdr_arg : décodage des arguments xdr_res : encodage du résultat

Coté client  :   Appel distant : callrpc callrpc(machine, prog, version, proc,xdr_arg, arg, xdr_res, res) machine : adresse IP de la machine arg : pointe sur les paramètres de la procédure xdr_arg : spécifie le traitement XDR correspondant res : pointe sur le résultat de la procédure xdr_res : pointe sur le traitement XDR correspondant callrpc renvoi 0, si l’appel est exécuté

Exemple : un client envoi un couple de réels à un serveur on lui demandant de réaliser une des opérations suivantes : addition, soustraction, ou la multiplication a, b float add(float a, float b) float diff(float a, float b) float mult(float a, float b) res

Fonctions XDR :   Fichier head.c # include <rpc/type.h> # include <rpc/xdr.h> typedef struct couple { float a; float b ; } couple; /*xdr_float codage (XDR)*/ int xdr_couple(XDR *xdrp, couple *p) { return(xdr_float(xdrp, &p->a) && xdr_float(xdrp, &p->a)) }

Codage des fonctions du serveur #include " head.h"  float *add(struct couple *p) { static float res ; res = p->e1 + p->e2 ; return (&res) ; }  char *mult(struct couple *p) { static float res ; res = p->e1 * p->e2 ;   main() {/*enregistrement de l’addition*/ int registerrpc(prog, 1, 1, add, xdr_couple, xdr_float)  /*enregistrement de la multiplication*/ int registerrpc(prog, 1, 2, mult, xdr_couple, xdr_float) /*mise en attente du serveur */ svc_run ( ) ; }

Codage du client   #include " head.h" main(int argc, char *argv[]) { float res ; struct couple data; data.a =atof(argv[0]); data.a =atof(argv[1]); /* appel de l’addition */ callrpc(“170.0.5.2”, 1, 1, 1, xdr_couple, &don, xdr_float, &res); printf(“résultat de l’addition :%f ”, res) ;  }

Le générateur rpcgen

rpcgen permet d’obtenir des programmes répartis à partir de leur spécification. On décrit les données et les programmes grâce à un langage voisin du C dans un fichier suffixé « .x » (prog.x). On traite ce fichier par le générateur rpcgen. Il produit :   ·      Un fichier d’en-tête : prog.h ·      Deux fichiers clients : prog_clnt.c et prog_xdr.c ·      Deux fichiers serveurs : prog_svc.c et prog_xdr.c On peut créer du C ANSI avec la commande rpcgen -C. Les programmes client.c et serveur.c restent à la charge du programmeur.

Les données de rpcgen Le fichier de données est suffixé « .x » 1. On définit les données en entrée et en sortie. Une fonction a au plus un paramètre d’entrée et un de sortie. On doit donc avoir recours à des structures pour des appels avec plusieurs paramètres. 2. Les structures sont éventuellement redéfinies grâce à typedef typedef données en entrée typedef données en sortie 3. On déclare ensuite le programme et l’ensemble des procédures appelées à distance

Le client a besoin de connaître le nom symbolique du serveur (numprog,numver) et ses procédures * Publication dans un contrat (fichier .x) * Langage RPCL n Le serveur a besoin des implémentations des procédures pour pouvoir les appeler * Fichier contenant les implémentations des procédures n Serveur et client ont besoin des stubs de communication * Communication transparente ==> génération automatique des stubs et des fonctions XDR de conversion de paramètres * RPCGEN (compilateur de contrat)

Le langage RPCL n Constantes *Const nom=valeur; n Enumérations et structures *Idem C n Unions *Idem structures avec variantes en Pascal n Tableaux *<type_de_base> <nom_tab> <TAILLE> (ex : int toto<MAXSIZE>) n Définition de types *typedef

Forme générale du contrat /* Définitions de types utilisateur */ ... program «nomprog» { version «nomversion1» { «typeres1» PROC1(«param1») = 1; «typeresn» PROCn(«paramn») = n; } = 1; version «nomversionm» { } = m; } = «numéro_du_programme»;

Méthodologie de développement Ecrire le contrat prog.x dans le langage RPCL n Compiler le contrat avec RPCGEN *prog.h : déclarations des constantes et types utilisés dans le code généré pour le client et le serveur *prog_xdr.c : procédures XDR utilisés par le client et le serveur pour encoder/décoder les arguments, *prog_clnt.c : procédure stub côté client *prog_svc.c : procédure stub côté serveur n Ecrire le client (client.c) et le serveur (serveur.c) *Serveur.c : implémentation de l’ensemble des procédures

Le squelette général d’un client est le suivant : #include <rpc/rpc.h> #include "prog.h" void client() { CLIENT *cl; /* RPC handle */ typeIn entrée; /* param entrée */ typeOut *out; /* param sortie */ char *serveur;   cl = clnt_create(serveur, PROGRAMME, VERSION , "udp"); out = proc_un_1(&entrée, cl); clnt_destroy(cl); }

Le nom des services est généré automatiquement par rpcgen Le nom des services est généré automatiquement par rpcgen. à partir du fichier « .x ». #include <rpc/rpc.h> #include "prog.h" TypeOut *proc_un_1(entrée) TypeIn *entrée; { static typeOut sortie; /* Doit être static */ … return &sortie; }

Quelques points à retenir ü      Le nom des procédures à distance doit être écrit en majuscules. ü      Les appels ne doivent pas comporter plus d’un paramètre. ü      Les passages des paramètres et leur retour doivent se faire par des pointeurs. Le paramètre de retour des procédures de service doit être déclaré en static La production de code L’outil rpcgen produit : ü      un fichier d’en-tête : prog.h ü      deux stubs : prog_clnt.c et prog_svc.c ü      un filtre XDR : et prog_xdr.c Le programmeur produit : serveur.c, client.c Le compilateur produit : ü      Le client avec : client.c, prog_clnt.c, prog_xdr.c ü      Le serveur avec : serveur.c, prog_svc.c, prog_xdr.c.

Exemple Fichier add.x struct intpair { int a; int b; }; program ADDPROG { version ADDVERS { int ADDPROC_ADD(intpair) = 1; int ADDPROC_MULT(intpair) = 2; } = 1; } = 73;

rpcgen –a add.x add.h , add_svc.c, add_clnt.c, add_xdr.c puis exemple de fichier add_client.c et add_server.c Et un Makefile.add

add_client.c il demande successivement: l'ouverture d'une session: cl = clnt_create(argv[1],ADDPROG,ADDVERS,"tcp"); Le protocole utilisé peut être TCP ou UDP. … main(int argc, char *argv[]) { char *host; if (argc < 2) { printf("usage: %s server_host\n", argv[0]); exit(1); } host = argv[1]; add_prog_1(host); }

int main(int argc, char *argv[]) { char *host; int a, b; if (argc != 4) { printf ("usage: %s server_host num1 num2\n", argv[0]); exit(1); } host = argv[1]; if ((a = atoi(argv[2])) == 0 && *argv[2] != '0') { fprintf(stderr, "invalid value: %s\n", argv[2]); exit(1); } if ((b = atoi(argv[3])) == 0 && *argv[3] != '0') { fprintf(stderr, "invalid value: %s\n", argv[3]); exit(1); } add_prog_1(host, a, b); }

add_server.c /* * RPC server code for the remote add function */ #include "add.h" int * add_1_svc(intpair *argp, struct svc_req *rqstp) { static int result; /* doit être static */ result = argp->a + argp->b; printf("add(%d, %d) = %d\n", argp->a, argp->b, result); return &result; }