Está en la página 1de 6

RPC (Remote Procedure Call)

Concepto de RPC
En unix es posible tener en ejecucin un programa en C con varias funciones
que pueden ser llamadas desde otro programas. Estos otros programas pueden
estar corriendo en otros ordenadores conectados en red.
Supongamos, por ejemplo, que tenemos un ordenador muy potente en clculo
matemtico y otro con un buen display para grficos. Queremos hacer un
programa con mucho clculo y con unos grficos "maravillosos". Ninguno de los
dos ordenadores cumple con ambos requisitos. Una solucin, utilizando RPC
(Llamada a procedimientos remotos), consiste en programar las funciones
matemticas en el ordenador de clculo y publicar dichas funciones. Estas
funciones podrn ser llamadas por el ordenador grfico, pero se ejecutarn en
el ordenador de clculo. Por otro lado, hacemos nuestros grficos en el
ordenador grfico y cuando necesitemos algn clculo, llamamos a las
funciones del ordenador de clculo.
Al programa con las funciones se le llama "servidor". Al programa que llama a
esas funciones se le llama "cliente". Normalmente el servidor est siempre
corriendo y a la espera de que algn cliente llame a alguna de sus funciones..
Cuando el cliente llama a una funcin del servidor, la funcin se ejecuta en el
servidor y el cliente detiene su ejecucin hasta que el servidor termina.
En el cdigo del programa servidor bsicamente hay que seguir los siguientes
pasos:
Codificar las funciones que van a ser llamadas siguiendo un determinado
mecanismo.
Informar al sistema operativo (unix) de un nombre, una versin y funciones que
publica.
Meterse en un bucle infinito esperando que alguien llame a alguna de sus
funciones.
Mientras que el programa cliente debe:
Establecer una conexin con el servidor.
Llamar a las funciones.

Cerrar la conexin con el servidor.

EL PROGRAMA RPCGEN
Afortunadamente en unix existe una utilidad llamada rpcgen que nos ayuda en
todo el proceso de codificacin. En un lenguaje similar a C (pero no igual)
definimos los prototipos de las funciones que queremos que se publiquen.
Habitualmente dicho fichero suele tener la extensin ".x". Luego, con el
comando de unix
rpcgen -a fichero.x
se generan varios ficheros (7 en concreto) con todo el cdigo hecho, excepto,
naturalmente, el cdigo de las funciones que queremos publicar.
Si no ponemos la opcin -a, se generarn menos ficheros, dejndonos a
nosotros el trabajo de generar los siguientes. El motivo es que sin la opcin -a
se generan nicamente los ficheros con las funciones (vacias, para que las
rellenemos). Con la opcin -a se generan adems unos ejemplos de uso, que
pueden ser tiles siempre y cuando estemos dispuestos a modificarlos. En el
resto del texto suponemos siempre que se ha usado la opcin -a.
El servidor que genera rpcgen tiene todo prcticamente hecho, con la
excepcin de que nuestras funciones estn casi vacias (devuelven un valor por
defecto). Tenemos que editar y rellenar el cdigo de nuestras funciones.
El cliente que genera rpcgen tiene tambin todo hecho. Se conecta al servidor,
llama a todas las funciones una por una y cierra la conexin. Obviamente
aprovechamos el principio (la conexin) y el final (la desconexin). Las llamadas
a las funciones deberamos borrarlas y hacer que el cliente haga lo que
nosostros queramos.
Veamos un pequeo ejemplo de un fichero.x
program NOMBRE_PROGRAMA {
version VERSION_PROGRAMA {
int incrementa (int) = 1;
} = 1;
} = 0x20000001;

El fichero comienza con la palabra "program" y el nombre que queramos dar a


nuestro programa. Despus, entre llaves va el resto. Al final todo se iguala a un
nmero (= 0x20000001; ). Este nmero debe ser nico para cada programa. De
esta forma podemos tener varios servidores corriendo a la vez en el mismo
ordenador y los clientes tendrn una forma de referenciarlos.
Dentro de las llaves del programa va "version" con el nombre de la version y,
despus de la estructura de llaves, igualado a un nmero de versin ( = 1; ).
Esto permite tener corriendo varias versiones del mismo programa (y de las
mismas funciones) a la vez. Los clientes pueden indicar a qu versin quieren
llamar.
Finalmente, dentro de las llaves de versin, van los prototipos de nuestras
funciones. Cada funcin se iguala a un nmero ( = 1; ) distinto, de forma que el
cliente referenciar a la funcin por su nmero. Todas las funciones deben
admitir un nico parmetro. Si queremos pasar ms de un parmetro,
deberemos hacernos una estructura con los campos necesarios. Lo mismo pasa
con el retorno de la funcin, puede ser un tipo simple o una estructura.
El lenguaje admite la declaracin de estructuras para pasar parmetros
complejos. Si queremos una funcin que admita varios parmetros, debemos
hacer una estructura con todos esos parmetros. La funcin admitir como
nico parmetro una estructura de este tipo.
Por ejemplo, si nuestra funcin es "int suma (int sumando1, int sumando2);", el
fichero suma.x debera contener algo parecido a lo siguiente:
struct sumandos
{
int sumando1;
int sumando2;
};
program PROGRAMA_SUMA {
version VERSION_SUMA {
int suma (sumandos) = 1;
} = 1;
} = 0x20000001;
Ficheros generados por rpcgen

Una vez escrito nuestro fichero suma.x, hacemos una llamada al comando de
unix "rpcgen -a suma.x". Esto generar 7 ficheros distintos (Puedes "pinchar" el
nombre del fichero para verlo. Si lo descargas, qutale la extensin ".txt").
Makefile.suma. Es el fichero Makefile necesario para compilar todos los dems
ficheros de cdigo generados por rpcgen. El comando de unix "make -f
Makefile.suma" nos generar los ejecutables de cliente y servidor.
suma_xdr.c. Como RPC permite llamadas de clientes a servidores que estn en
mquinas distintas y, por tanto, puedan tener una arquitectura distinta, es
necesario traducir los parmetros y resultados a un "cdigo" universal,
independiente de las mquinas. Si los parmetros son tipos bsicos (int, float,
char, etc), el sistema unix ya tiene unas funciones de conversin (xdr_int(),
xdr_float(), etc). Si los parmetros, como en este caso, son estructuras
definidas por nosotros, las funciones de conversin hay que hacerlas. rpcgen
genera automticamente dichas funciones y en nuestro caso, las ha metido en
el fichero suma_xdr.c
suma.h. Aqu estn los prototipos de nuestras funciones. Cualquier cliente que
quiera usarlas, deber hacer un include de este fichero. El prototipo no es
exactamente como esperaramos. A cada funcin le aade en el nombre unas
"coletillas" para indicar el nmero de versin. Define tambin otras constantes
como nombre de programa, nmero de versin, etc, que son tiles a la hora de
hacer la conexin con el servidor.
suma_server.c. En este fichero estn nuestras funciones, vacas, por supuesto.
Debemos editarlo y escribir aqu nuestro cdigo. Veamos el fichero con un poco
de detalle:
int * suma_1_svc(sumandos *argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = argp->sumando1 + argp->sumando2; /* Esta lnea debe
hacerla el programador */
return &result;
}

Al nombre de la funcin suma le ha aadido _1_svc. Indica que es la


parte del servidor, versin 1. Declara un "result" esttico del tipo que le
hayamos indicado como retorno en el fichero .x. Debemos dejar en esa
variable nuestro resultado. Pone un comentario para indicarnos que
escribamos ah nuestro cdigo. El programador escribe el cdigo. Recibe
en argp un puntero a una estructura con los datos que le pasa el cliente.
Con ella echa las cuentas y las guarda en "result". rpcgen pone la lnea
"return &result"
suma_svc.c. Este es un ejemplo concreto de servidor. Normalmente nos vale tal
cual. Bsicamente registra al servidor en el sistema unix para indicarle que
atienda a las llamadas y proporciona un "switch-case" para llamar a cada una
de las funciones al recibir una peticin de un cliente.
suma_client.c. Este es el main de un cliente concreto. Establece la conexin con
el servidor de rpc, llama a todas las funciones una a una y cierra la conexin.
Normalmente este cliente no nos sirve para nada. Lo habitual es hacerse un
cliente a medida, copiando las funciones de establecimiento de conexin
"clnt_create()" y las de desconexin "clnt_destroy()". El resto del cliente es
nuestro programa y usaremos llamadas a "suma_1()" o la funcin que sea
cuando lo necesitemos. "clnt_create()" nos devuelve un "identificador" de
cliente. Deberemos usar este valor en todas las dems llamadas a funciones y
"clnt_destroy()".
suma_clnt.c. Las llamadas a funciones de rpc desde un cliente son ms o
menos complejas. Se hacen a travs de la funcin "clnt_call()" que lleva la
friolera de 7 parmetros. En "suma_clnt.c" rpcgen mete unas funciones de
"traduccin" para hacernos ms sencillas las llamadas desde nuestro cliente.
As, bastar con llamar a "suma_1()" con un par de parmetros simples
(nuestros datos y el identificador obtenido con "clnt_create()"), en vez de usar
"clnt_call()" con 7 parmetros distintos (identificador de cliente, identificador de
la funcin a llamar, funcin de conversin del parmetro de entrada, parmetro
de entarada, etc, etc).
Para ejecutar el ejemplo...
El ejemplo crea un servidor que publica una funcin de sumar dos enteros.
Luego un cliente se conecta, pide una suma al servidor pasndole dos enteros y
escribe el resultado en pantalla.
Debes descargar todos los ficheros mencionados en un directorio. Luego compilas
con "make -f Makefile.suma", con lo que se generan dos

ejecutables: suma_server ysuma_client. Ejecutas el servidor desde una shell con


"suma_server". Luego ejecutas el cliente con "suma_client <maquina_servidor>" y
ves el resultado.<maquina_servidor> es el nombre de la mquina donde has
ejecutado el suma_server. Si es en la misma mquina, puedes poner de nombre
de mquina "localhost".
En este video puedes ver todo el proceso:

También podría gustarte