Para construir una aplicación distribuida usando RPC se debe seguir el siguiente procedimiento: 1) Construir y probar una aplicación convencional que resuelva el problema (en funciones) 2) Escribir una especificación rpcgen para generar las estructuras del cliente y servidor. 3) En el cliente llamar a la función. 4) En el servidor colocar la función que resuelve el problema (la del punto 1). 5) Compilar cliente y el servidor. 6) Ejecutar el servidor en la máquina remota, y el cliente en la local. Observación: Se deben tener activados los servicios y puertos: portmap y todos los que contienen “rpc”. Descripción detallada de los pasos anteriores, aplicada a un ejemplo de función “Suma” PASO 1: El código que se muestra a continuación, implementa la suma de 2 valores, en forma de función, para una fácil distribución de la aplicación. #include <stdio.h> #include <stdlib.h> void main(void) { int x, y; int suma(int a, int b); printf (“Ingrese valores para X e Y”); scanf (“%d%d”, x, y); } int suma(int a, int b) { return (a + b); } PASO 2: Se escribe una especificación rpcgen para crear estructuras, que es básicamente una declaración de un programa remoto y de las estructuras de datos que se utilizarán. Este archivo de puede contener: a) Declaraciones de constantes utilizadas por el cliente, y, más a menudo, del servidor. b) Declaraciones de los tipos de datos utilizados, especialmente como argumentos de los procedimientos remotos. c) Declaraciones de programas remotos, los procedimientos que estos contienen y los tipos de sus parámetros. Definición del protocolo para el ejemplo, archivo suma.x El archivo de especificación suma.x tiene la forma: /* suma.x -- archivo de definicion del protocolo escrito en lenguaje RPC que se pasa al comando rpcgen. Cada procedimiento es a parte de un programa remoto. Cada procedimiento tiene un nombre y numero. Se suministra un numero de version para poder generar diferentes versiones del mismo procedimiento */ struct datos { int a; int b; }; program SUMA_PRG { version UNO { int suma (struct datos) = 1; } = 1; } = 0x20000002; Tabla 1.- Número de programas utilizados en RPC. Rango Valores asignados por 0x00000000-0x1fffffff Sun Microsystems 0x20000000-0x3fffffff Administrador del sistema local 0x40000000-0x5fffffff Transitorios (temporales) 0x60000000-0x7fffffff Reservados (definidos por usuario) 0x80000000-0x9fffffff Reservados (definidos por usuario) 0xa0000000-0xbfffffff Reservados (definidos por usuario) 0xc0000000-0xdfffffff Reservados (definidos por usuario) 0xe0000000-0xffffffff Reservados (definidos por usuario) Rango Valores asignados por Tabla 2.- Algunos ejemplos de números de programa asignados por Sun. Nombre portmap nfs Número 100000 100003 Descripción Port mapper Network File System NOTA: Posteriormente a la creación del archivo X se utiliza el comando RPCGEN (en la linea de comandos) para generar las aplicaciones cliente y servidor (estructuras): rpcgen suma.x rpcgen -a suma.x rpcgen -C suma.x Una vez realizado este proceso se generan los siguientes archivos: suma_server.c suma_svc.c suma_client.c suma_clnt.c suma.h PASO 3: Se modifican las rutinas en el cliente, archivo suma_client.c. Las líneas negritas y cursivas se han agregado. #include "suma.h" #include <stdio.h> #include <stdlib.h> void suma_prg_1(char *host) { CLIENT *clnt; int *result_1; struct datos suma_1_arg; #ifndef DEBUG clnt = clnt_create (host, SUMA_PRG, UNO, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } #endif /* DEBUG */ printf ("Ingrese 2 Nros\n"); scanf ("%d%d", &suma_1_arg.a, &suma_1_arg.b); result_1 = suma_1(&suma_1_arg, clnt); if (result_1 == (int *) NULL) { clnt_perror (clnt, "call failed"); } printf ("El resultado es %d\n", *result_1); #ifndef DEBUG clnt_destroy (clnt); #endif /* DEBUG */ } /* La var argc es el numero de parámetros llamados Ej: ./cliente 10.20.20.189, se guarda 2 */ /* La var argv es un arreglo argv[0]=” cliente” argv[1]=” 10.20.20.190”, “separa lo ingresado” */ int main (int argc, char *argv[]) { char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; suma_prg_1 (host); exit (0); } PASO 4: En el servidor se inserta la función que resuelve el problema. #include "suma.h" #include <stdio.h> #include <stdlib.h> int * suma_1_svc(struct datos *argp, struct svc_req *rqstp) { static int result; /* * insert server code here */ printf ("Se reciben %d %d\n", argp->a, argp->b); result = argp->a + argp->b; printf ("Se envia %d\n", result); return &result; } PASO 5: Compilar el programa cliente y el servidor. cc suma_clnt.c suma_client.c suma_xdr.c –o cliente cc suma_svc.c suma_server.c suma_xdr.c –o server PASO 6: Ejecutar el servidor en la máquina remota, y el cliente en la local. ./Server ./cliente 10.20.20.189 (Ejecución y resultado final en cliente y en el servidor)