Arquitectura cliente-servidor¶
Introducción a los sistemas distribuidos¶
Un sistema distribuido es un conjunto de ordenadores que realizan alguna tarea de forma conjunta, para lo que se debe disponer de una red mediante la cual puedan comunicarse. La forma más extendida para permitir la compartición de recursos (discos duros, impresoras, ficheros, bases de datos, etc.) en un sistema distribuido es el uso del modelo cliente–servidor. Un servidor es un programa que se ejecuta en un ordenador y que se encarga de gestionar un recurso o conjunto de recursos. Los clientes son programas que harán peticiones de servicio, a través de la red, al servidor para obtener acceso a los recursos que gestiona.
Los servidores facilitan acceso a los recursos del sistema, formando parte del sistema operativo distribuido. No todos los recursos del sistema se pueden gestionar eficientemente por servidores –como, por ejemplo, la memoria–, siendo gestionados por el núcleo del sistema operativo presente en cada ordenador.
La comunicación mediante sockets¶
Introducción¶
Un socket es un mecanismo de comunicación entre dos o más procesos,
gracias al cual es posible enviar o recibir información. A efectos de
programación un socket funciona como un descriptor de ficheros de bajo
nivel; comandos como read()
y write()
funcionan con sockets de la
misma forma que lo hacen con ficheros y tuberías.
El conjunto de servicios que ofrece un socket fue diseñado para facilitar una conexión entre procesos, tanto si se ejecutan en una sola máquina, como si lo hacen en red. Los procesos se intercambian información transmitiendo datos a través de mensajes que circulan entre un socket en un proceso y otro socket en otro proceso. Para la comunicación entre máquinas se suelen utilizar los protocolos TCP/IP, logrando así la independencia del hardware y de la arquitectura de red mediante la cual se establece el enlace; siendo esto posible gracias a la estructura en forma de capas que posee una red de ordenadores (véase [sec:capas]{reference-type=”ref” reference=”sec:capas”}). Los sockets son conexiones que pertenecen a la capa de transporte de la estructura OSI. Una aplicación con sockets debe especificar los puertos de protocolo local y remoto y la dirección IP remota que utilizará, si usará TCP o UDP, y si iniciará transferencia o esperará por una conexión (es decir, si funcionará como servidor o cliente).
Tipos de sockets¶
El mecanismo de sockets está diseñado de forma genérica; un socket por sí mismo no contiene información suficiente para describir la comunicación entre procesos. Los sockets operan dentro de dominios de comunicación, que determinan el formato de direcciones a utilizar y el protocolo de comunicación. Además el dominio difine si los dos porcesos que se comunican se encuentran en el mismo sistema o en sistemas diferentes y cómo pueden ser direccionados. De esta forma un socket puede clasificarse según su dominio y según el tipo de conexión que realice.
En función del tipo de conexión se dispone de varios tipos de socket, que describen la forma en la que se transfiere información a través de ese socket: sockets stream, sockets datagrama y sockets raw.
- Los sockets stream son un servicio orientado a conexión donde los datos se transfieren sin encuadrarlos en registros o bloques. Para establecer una comunicación utilizando el protocolo TCP.
- Los sockets datagrama son un servicio de transporte si conexión que utilizan el protocolo de transporte UDP. Cada vez que se envían datagramas es necesario enviar el descriptor del socket local y la dirección del socket que deve recibir el datagrama. Por tanto, hay que enviar datos adicionales cada vez que se realice una comunicación. Los datos se envían y reciben en paquetes cuya entrega no está garantizada.
- Los sockets raw dan acceso 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. Los sockets raw proporcionan acceso al Internet Control Message Protocol, ICMP, y se utiliza para comunicarse entre varias entidades IP.
Con respecto a la clasificación en función del dominio, bajo Unix existen dos dominios: uno para comunicaciones internas al sistem (dominio UNIX) y el otro para comunicaciones entre sistemas (dominio Internet). El dominio UNIX (AF_UNIX) permite una comunicación intrasistema entre procesos que corren en el mismo microprocesador. Se permiten tanto los sockets stream como los datagrama; no se permiten los sockets de tipo raw. El dominio Internet (AF_INET) soporta los protocolos estándar de Internet TCP y UDP y se utiliza para comunicar procesos que corren en distintos microprocesadores. Permite sockets stream, datagrama y raw.
Programación con sockets¶
Las llamadas al sistema más significativas son:
-
socket()
crea un nuevo socket que puede ser utilizado para comunicación en red. Tiene tres argumentos:- dominio o familia de direcciones a la que pertenece el socket (AF_UNIX, AD_INET),
- tipo de socket a crear (SOCK_STREAM, SOCK_DGRAM),
- protocolo (en general, toma el valor 0).
socketpair()
es muy similar asocket()
excepto en que se crean dos sockets conectados.
-
bind()
asigna un nombre a un socket que no lo tiene. Conbind()
el servidor registra su dirección en el sistema de manera que los mensajes recibidos con su dirección le sean entregados. La llamada abind()
tiene como argumentos:- descriptor de fichero del socket, obtenido con la llamada a
socket()
,
- nombre asignado al socket,
- longitud del nombre.
bind()
sólo permite especificar una dirección local. - descriptor de fichero del socket, obtenido con la llamada a
connect()
es similar abind()
, pero se utiliza para especificar la dirección de conexión a una máquina remota.
-
read()
ywrite()
pueden ser utilizadas tanto por el servidor como por el cliente para enviar y recibir mensajes. Los clientes utilizanwrite()
para enviar peticiones, mientras que los servidores la utilizan para enviar réplicas. Una llamada awrite()
requiere tres argumentos:- descriptor del socket al cual enviar los datos,
- datos a enviar,
- longitud de los datos.
Los servidores utilizan
read()
para recibir las peticiones que realizan los clientes con la llamadawrite()
. Después de enviar su petición, el cliente utilizaread()
para recibir la réplica. Para leer una conexiónread()
dispone de tres argumentos:- descriptor del socket a utilizar,
- dirección de un búfer,
- longitud máxima de dicho búfer.
read()
extrae los bytes de datos que llegan al socket y los copia en el búfer.
close()
, se utiliza para eliminar un socket una vez que un cliente o un servidor finaliza su uso.
-
listen()
yaccept()
permiten al servidor escuchar soliciturdes de servicio (también pueden utilizarsesend()
yrecv()
).listen()
establece el socket como el punto final pasivo de una conexión, no suspendiendo la ejecución del proceso; no pueden enviarse mensajes a través de este socket, pero sí pueden recibirse mensajes de entrada. Dispone de dos argumentos:- descriptor de fichero asociado con el socket creado usando la
llamada al sistema
socket()
,
- tamaño de la cola de solicitudes que esperan mientras el servidor está ocupado cumplimentando una solicitud de servicio.
- descriptor de fichero asociado con el socket creado usando la
llamada al sistema
-
connect()
, con esta función el cliente solicita la conexión. El servidor, previamente, habrá creado el cliente consocket()
, lo habrá etiquetado conbind()
, y habrá establecido una cola de escucha usandolisten()
. Los argumentos que recibe son:- descriptor de fichero de socket devuelto por la función
socket()
,
- nombre del socket.
Después de un retorno con éxito desde
accept()
, esta estructura contendrá la dirección de protocolo del socket del clente. Este neuvo socket será utilizado para todas las comunicaciones con el cliente. Si no hay ninguna solicitud de conexión en espera,accept()
se bloqueará hasta que se coloca en la cola una solicitud de un cliente. - descriptor de fichero de socket devuelto por la función
Conexiones cliente–servidor¶
Para la mayor parte de las operaciones que utilizan sockets es necesario asignar los papeles de cliente y servidor. Un servidor es un proceso que realiza alguna función a petición del cliente. Estos papeles no son simétricos y no pueden ser invertidos sin esfuerzo. Existen dos tipos de servidores: iterativo y concurrente.
Un servidor iterativo en el dominio Internet es aquel que atiende a los clientes uno detrás de otro, es decir, el servidor iterativo atiende las peticiones en serie. Un servidor de este tipo es el demonio nfsd que proporciona el servicio NFS