RPC (Llamadas a procedimientos remotas)
Es una técnica para desarrollar aplicaciones donde
se requiere la comunicación entre procesadores que cooperan en un sistema
distribuido.
Este puede interactuarce con un servidor
computacional o con una Base de Datos, y ha sido usado por algunos sistemas para
proporcionar para acceso a servicios del sistema operativo.
Las RPC son expresadas como procedimientos
ordinarios. Estas llamadas no requieren un compilador especial para el código
fuente del programa.
Ventajas:
-
Transparencia: La capa RPC puede ser reemplazada con llamadas a
funciones directas si llegan a estar disponibles.
-
Familiaridad
del interface: La
mayoria de programadores estan acostumbrados a una forma de llamadas a
procedimientos. Esto permite una fácil adaptación al mecanismo RPC en sistemas
ya implantados.
Cuando se realiza una llamada a procedimiento,
normalmente se usa la pila,
poniendo los parámetros en ella y reservando
espacio para las variable locales, tal y como vemos en la siguiente figura:
Las RPC son realmente una manera de ocultar el
protocolo de pase de mensajes. Esto proporciona una manera adecuada de permitir
una interpretación a alto nivel, abstrayendo el mecanismo de comunicación a
bajo nivel, es decir haciendo transparente al programador el protocolo de red.
La mayor ventaja de usar el mecanismo RPC es para
permitir que una aplicación realice una simple llamada a función a un
interface conocido. El mecanismo RPC proporciona un stub que empaqueta los
argumentos en una forma sencilla, para ser transmitidos bajo una red a otro
sistema, donde los argumentos son desempaquetados por otro stub en el proceso
servidor y pasados a la función actual o procedimiento que ha sido llamado.
Stub:
llamada a procedimiento actual se realize para activar el sistema RPC.
Un ejemplo típico de RPC es el servicio remote_time que retorna la hora de una máquina remota como un string, que se muestra a continuacion:
int remote_time(char *machine, char *time_buf)
{
struct sockaddr_in serv_addr;
int sockfd;
int nread;
if (sockfd = socket(AF_INET,SOCK_STREAM, 0))< 0)
return 1;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(machine);
serv_addr.sin_port = htons(13);
if (connect(sockfd,&serv_addr,sizeof(serv_addr))< 0)
return 2;
nread = read(sockfd,time_buf,sizeof(time_buf));
time_buf[nread] = '\0';
close(sockfd);
return 0;
}
Remote Procedure Call (El Modelo RPC)
El modelo RPC describe como al cooperar procesos en diferentes nodos de una red pueden comunicarse y coordinar sus actividades. El paradigma de RPC está basado en el concepto de una llamada a un procedimiento en un lenguaje de programación. La semántica de RPC es muy parecida a la semántica de las tradicionales llamadas a procedimientos. La mayor diferencia es que mientras una llamada a procedimiento normal se realiza entre procedimientos de un proceso simple en el mismo espacio de memoria, una RPC se realiza entre un proceso cliente de un sistema (o máquina) y un proceso servidor de otro sistema, donde ambos, la máquina del cliente y la máquina del servidor están conectadas a una red.
La figura ilustra las operaciones básicas de RPC.
Donde:
1.Una aplicación cliente ejecuta una llamada a
procedimiento a un stub cliente. El stub cliente recibe los argumentos de la
llamada a procedimiento, convierte el argumento de entrada de la representación
de datos local a una representación de datos comun, empaquetandolos en un
mensaje que contiene el argumento de entrada en su representación de datos
comun. Este proceso se denomina "marshalling"
2.El
stub cliente llama a las funciones de red del kernel del SO para enviar el
mensaje.
3.El kernel envia el mensaje al sistema remoto. Esta comunicación puede ser orientada a conexión (protocolo TCP) o a no conexión (protocolo UDP).
4.El
stub servidor desempaqueta los argumentos del mensaje de red, convirtiendolos a
la representación de datos propia
del servidor.
5.El
stub servidor llama a la aplicación local del servidor que realiza la ejecución.
6.El
procedimiento se completa, retornando los resultados de la ejecución al stub
servidor.
7.El
stub servidor empaqueta los valores de retorno en un mensaje de red,
conviertiendolos a una representación de datos
común.
8.El
mensaje de retorno es enviado.
9.El
stub cliente lee el mensaje utilizando las funciones de red suministradas por el
kernel del Sistema Operativo.
10.El
mensaje es desempaquetado y convertido a la representación de datos del
cliente, y el valor de retorno se pone en la pila para el proceso local.
La RPC no se adapta perfectamente al Modelo de Referencia OSI. Se ha diseñado para ser rápida y, por lo tanto, no contiene una estructura de múltiples capas. La llamada de procedimientos remotos está interesada en aproximadamente los mismos temas que la capa de sesión por lo que consideraremos a la RPC como una capa de sesión un tanto especial por tratarse de una capa de sesión sin conexión.
La RPC sigue el modelo cliente-servidor el cliente
es el proceso que realiza la llamada al RPC y el servidor el proceso remoto. La
diferencia con otros sistemas cliente-servidor es que ahora la comunicación se
hace por medio de llamadas a procedimientos.
La realización de una llamada a procedimiento remoto comienza con una llamada normal, de tipo local ya que el programa cliente no sabe que ese procedimiento no se encuentra en la maquina local. Esta llamada ejecuta el procedimiento cabo de cliente.
El cabo del cliente, entonces, colecta los parámetros
y los empaqueta en un mensaje. Esta operación se conoce como
encapsulado de parámetros. Este mensaje se pasa a través de la red
hasta el cabo de cliente del servidor, el cual se encarga de desencapsular los
parámetros. El procedimiento cabo del servidor entonces llama al procedimiento
servidor, pasando los parámetros en la forma normal. El servidor no tiene
ninguna manera de notar que está siendo activado de forma remota, porque el que
está haciendo la llamada, es un procedimiento local que obedece todas la reglas
normales.
Los sockets son puntos finales de enlaces de
comunicaciones entre procesos. Los procesos los tratan como descriptores de
ficheros, de forma que se pueden intercambiar datos con otros procesos
transmitiendo y recibiendo a través de sockets.
El tipo de sockets describe la forma en la que se
transfiere información a través de ese socket.
Sockets Stream (TCP, Transport Control Protocol)
Son un servicio orientado a conexión donde los
datos se transfieren sin encuadrarlos en registros o bloques. Si se rompe la
conexión entre los procesos, éstos serán informados.
El protocolo de comunicaciones con streams es un
protocolo orientado a conexión, ya que para establecer una comunicación
utilizando el protocolo TCP, hay que establecer en primer lugar una conexión
entre un par de sockets. Mientras uno de los sockets atiende peticiones de
conexión (servidor), el otro solicita una conexión (cliente). Una vez que los
dos sockets estén conectados, se pueden utilizar para transmitir datos en ambas
direcciones.
Sockets Datagrama (UDP, User Datagram Protocol)
Son un servicio de transporte sin conexión. Son más
eficientes que TCP, pero no está garantizada la fiabilidad. Los datos se envían
y reciben en paquetes, cuya entrega no está garantizada. Los paquetes pueden
ser duplicados, perdidos o llegar en un orden diferente al que se envió.
El protocolo de comunicaciones con datagramas es un
protocolo sin conexión, es decir, cada vez que se envíen datagramas es
necesario enviar el descriptor del socket local y la dirección del socket que
debe recibir el datagrama. Como se puede ver, hay que enviar datos adicionales
cada vez que se realice una comunicación.
Son sockets que dan acceso directo a la capa de
software de red subyacente o a protocolos de más bajo nivel. Se utilizan sobre
todo para la depuración del código de los protocolos.
Ahora se nos presenta un problema, ¿qué
protocolo, o tipo de sockets, debemos usar - UDP o TCP? La decisión depende de
la aplicación cliente/servidor que estemos
escribiendo. Vamos a ver algunas diferencias entre los protocolos para ayudar en
la decisión.
En UDP, cada vez que se envía un datagrama, hay
que enviar también el descriptor del socket local y la dirección del socket
que va a recibir el datagrama, luego éstos son más grandes que los TCP.