Cliente Servidor
Cliente Servidor
El paradigma cliente-
servidor
C on ten ido
C onceptos básicos
Tipo de servidores
Servidores secuenciales y concurrentes
Servidores orientados a conexión y sin conexión
Servidores con/sin información de estado
Sesión:
interacción entre cliente y servidor
Ejemplo:
C liente-servidor con paso de mensajes
Guía de desarrollo de aplicaciones cliente-
servidor
2
U n a defin ició n simple …
3
Participantes
Elementos de
computación:
Cliente
Servidor
Red de interconexión
1) Petición
Red de interconexión
2) Respuesta
Máquina
Máquina del
cliente
servidor
4
Ejemplo: HTTP
1) Petición:
http://www.arcos.inf.uc3m.es
2) Respuesta
Cliente Servidor
1) Petición: 2) Respuesta:
GET /index.html HTTP/1.1 HTTP/1.1 200 OK
Host: www.example.com Date: Fri, 31 Dec 2003 23:59:59 GMT
User-Agent: nombre-cliente Content-Type: text/html
[Línea en blanco] Content-Length: 1221
<html>
<body>
<h1>Página www.uc3m.es</h1>
(Contenido) . . .
</body>
</html>
5
Acceso distribuido vs.
computació n distribuida
6
Cliente-Servidor
Asigna roles diferentes a los procesos que comunican: cliente y
servidor
Servidor:
O frece un servicio
Elemento pasivo: espera la llegada de peticiones
Cliente:
Solicita el servicio
Elemento activo: invoca peticiones
Servidor Cliente 1
Petición de
servicio Proceso
cliente Proceso
Cliente 2
..
servidor Servicio
.
7
Conceptos previos
El modelo cliente-servidor es una abstracción eficiente
para facilitar los servicios de red
La asignación de roles asimétricos simplifica la
sincronización
Implementación mediante:
Sockets
Llamada a procedimientos remotos (RPC )
Invocación de métodos remotos (RMI, C O RBA,
…).
Paradigma principalmente adecuado para
servicios centralizados
Ejemplos: servicios de Internet (HTTP, FTP,
8
D N S, … )
Tipos de servidores de aplicaciones
En función del número de peticiones que es capaz de atender:
Secuencial: una petición
Concurrente: múltiples peticiones atendidas al mismo tiempo
9
Modelo de servidor secuencial
El servidor sirve las peticiones de forma
secuencial
Mientras está atendiendo a un cliente no puede
aceptar peticiones de más clientes
petición
Cliente servidor
respuesta
10
Flujo de ejecució n de u n servidor
secuencial
Inicio de servicio
Aceptar petición de
sesión
Procesar la petición
del cliente
11
Servidor secuencial
Flujo de ejecució n de u n servidor
secuencial
Inicio de servicio
O btener
Aceptar petición de el
sesión resultado
+
Devolver la
respuesta al
Procesar la petición cliente
del cliente
Servidor
secuencial 12
Cliente-Servidor secuencial
Servidor Cliente 1
Solicitud
while(){ de
aceptar_peticio
Cliente 2 conexión
n() Sesión
tratar_peticion()
}
de
servicio
Cliente n
13
Cliente-Servidor secuencial
Servidor Cliente 1
Solicitud de
while(){ conexión
aceptar_peticio
n() Cliente 2
tratar_peticion()
Sesión de servicio
}
Cliente n
14
Cliente-Servidor secuencial
Servidor Cliente 1
Solicitud de conexión
while(){
aceptar_peticio
n() Cliente 2 Sesión de servicio
tratar_peticion()
}
Cliente n
15
Modelo de servidor concurrente
El servidor crea un hijo que atiende la petición y envía
la respuesta al cliente
Se pueden atender múltiples peticiones de forma
concurrente
petición
servidor
Cliente
Crea un proceso
hijo
respuest
a Proceso
hijo
16
Flujo de ejecució n de u n servidor
concurrente
Servidor
concurrente
Inicio de servicio
Aceptar petición
de sesión
C rear Procesar la fi
thread petición del n
Trabajador cliente 1
C
1 rear Procesar la fi
thread petición del n
Trabajador cliente 2
2
C rear Procesar la fi
thread petición del n
Trabajador cliente n
17
n
Flujo de ejecució n de u n servidor
concurrente
Servidor
concurrente O btener
Inicio de servicio el
resultado
+
Aceptar petición Devolver la
de sesión respuesta al
cliente
C rear Procesar la
fi
thread petición del n
Trabajador cliente 1
C
1 rear Procesar la fi
thread petición del n
Trabajador cliente 2
2
C rear Procesar la fi
thread petición del n
Trabajador cliente n
18
n
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_petici conexión
on() Cliente 2
pthread_create()
} Sesión de
servici
o
Cliente n
19
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticio conexión
n() Cliente 2
pthread_create()
} Sesión de
servici
o
Cliente n
20
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticion conexión
() Cliente 2
pthread_create(
) Sesión de
servici
}
o
Hilo
1 Cliente n
21
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticio conexión
n() Cliente 2
pthread_create()
} Sesión de
servici
o
Hilo
1 Cliente n
22
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticion conexión
() Cliente 2
pthread_create(
) Sesión de
servici
}
o
Hilo
1 Cliente n
Hilo
2
23
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticio conexión
n() Cliente 2
pthread_create()
} Sesión de
servici
o
Hilo
1 Cliente n
Hilo
2
24
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticion conexión
() Cliente 2
pthread_create(
) Sesión de
servici
}
o
Hilo
1 Cliente n
Hilo
2
Hilo n
25
Cliente-Servidor concurrente
Servidor Cliente 1
Solicitud
while() de
{ aceptar_peticio conexión
n() Cliente 2
pthread_create()
} Sesión de
servici
o
Hilo
1 Cliente n
Hilo
2
Hilo n
26
Diseñ o de servidores concurrentes
mediante threads
Distintas arquitecturas de SW para construir servidores paralelos:
Un proceso distribuidor que acepta peticiones y las distribuye entre un pool
de procesos ligeros
Cada proceso ligero realiza las mismas tareas: aceptar peticiones,
procesarlas y devolver su resultado
Segmentación: cada trabajo se divide en una serie de fases, cada una de
ellas se procesa por un proceso ligero especializado
Trabajador
Distribuidor
Solicitudes
Solicitudes
Solicitudes
Núcleo Núcleo Núcleo
E/S E/S E/S
27
Servidores orientados a conexió n
En un servicio orientado a conexión, el cliente y el
servidor establecen una conexión (que puede ser
lógica), posteriormente insertan o extraen datos
desde esa conexión, y finalmente la liberan
El flujo de tráfico se representa mediante un identificador
de conexión
Los datos no incluyen información sobre la
conexión establecida
Direcciones origen y destino
Ejemplo: T C P
28
Servidores sin conexió n
En un protocolo no orientado a conexión los
datos son intercambiados usando paquetes
independientes, auto-contenidos, cada uno de los
cuales necesita explícitamente la información
de conexión
N o existe acuerdo previo
Ejemplo: IP, U D P
29
Concepto de sesió n
Sesión: Interacción entre cliente y servidor
C ada cliente entabla una sesión separada e
independiente con el servidor
El cliente conduce un diálogo con el servidor hasta
obtener el servicio deseado
El servidor ejecuta indefinidamente:
Bucle continuo para aceptar peticiones de las sesiones de
los clientes
Para cada cliente el servidor conduce una sesión de servicio
30
Protocolo de servicio
Se necesita un protocolo para especificar las reglas
que deben observar el cliente y el servidor durante
una sesión de servicio
En cada sesión el diálogo sigue un patrón especificado por
el protocolo
Los protocolos de Internet están publicados en las RFCs
31
Tipos de servidores
Servidores sin estado:
Cada mensaje de petición y respuesta es independiente de
las demás
Ejemplo: HTTP
33
Arquitectura de S W
La arquitectura de SW de una aplicación cliente-
servidor consta de tres niveles:
Nivel de presentación: cliente y servidor precisan una interfaz de
usuario
Nivel de lógica de aplicación: en el lado del servidor necesita
procesarse la petición del cliente, calcular el resultado y devolverlo al
cliente. En el lado del cliente se necesita enviar al servicio la petición
del usuario y procesar el resultado (por ejemplo, mostrarlo por
pantalla)
Nivel de servicio: los servicios requeridos para dar soporte a la
aplicación son (1) en el servidor aquellos que permiten
procesar la petición y 2) el mecanismo de IPC
34
Arquitectura de las aplicaciones
Interfaz de usuario
Lógica de presentación
Lógica de aplicación
Lógica de servicio
35
¿Donde se ejecutan las tareas?
En el software del cliente (lado del cliente)
En el software del servidor (lado del
servidor)
36
Responsabilidades en el cliente
Cliente:
Genera un mensaje de petición de servicio
Se conecta al servidor (dirección IP y puerto) [Solo
orientado a conexión]
Envía el mensaje de petición de servicio
Espera por la respuesta
Procesa la respuesta: imprimir, almacenar, etc.
Desconexión [Solo orientado a conexión]
37
Responsabilidades en el servidor
Servidor:
1. Espera conexiones entrantes de los clientes
Una conexión entrante es una petición de servicio
2. Por cada conexión:
Genera un thread de servicio [Solo servidores
concurrentes]
El proceso principal:
Vuelve a esperar por nuevas conexiones entrantes
El thread de
servicio:
1. Procesa la petición
2. C alcula el
resultado
3. D evuelve la
respuesta al 38
cliente
4. Finaliza su
Aplicaciones cliente-servidor usando colas
de mensajes
Modelo proceso ligero distribuidor:
Cada petición al proceso ligero distribuidor supone la creación de
un proceso ligero trabajador
El proceso ligero trabajador responde al proceso cliente
Procesa la petición
Envía la respuesta al servidor
Una vez finalizada la sesión con el cliente, el proceso ligero se
destruye
Modelo concurrente:
Los procesos distribuidor y trabajador ejecutan de forma
concurrente
Modelo secuencial:
Sólo un proceso distribuidor
39
Ejemplo: sumar dos nú meros
Máquina A Máquina B
sumar(5,2)
cliente servidor
5+2
RED
40
@Fuente: Jesús Carretero, Félix García, Pedro de Miguel y Fernando Pérez. Mc Graw Hill
Ejemplo: Definició n de tipos
#define MAXSIZE 256
struct peticion {
int a; /* operando 1 */
int b; /* operando 2 */
char q_name[MAXSIZE]; /* nombre de la cola cliente
donde debe enviar la respuesta
el servidor */
};
41
Ejemplo: Proceso servidor secuencial
#include “mensaje.h”
#include <mqueue.h>
void main(void) {
mqd_t q_servidor; /* cola de mensajes del servidor */
mqd_t q_cliente; /* cola de mensajes del cliente */
struct peticion pet;
int res;
struct mq_attr attr;
attr.mq_maxmsg = 20;
attr.mq_msgsize = sizeof(struct peticion);
q_servidor = mq_open(“SERVIDOR_SUMA”, O_CREAT|O_READ, 0700, &attr);
while(1) {
mq_receive(q_servidor, &pet, sizeof(pet), 0);
res = pet.a + pet.b;
42
Ejemplo: Proceso cliente
#include “mensaje.h”
#include <mqueue.h>
void main(void)
{ mqd_t q_servidor; /* cola de mensajes del proceso servidor */
mqd_t q_cliente; /* cola de mensajes para el proceso cliente */
struct peticion pet;
int res;
struct mq_attr attr;
attr.mq_maxmsg = 1;
attr.mq_msgsize = sizeof(int);
q_cliente = mq_open(“CLIENTE_UNO”, O_CREAT|O_RDONLY, 0700, &attr);
q_servidor = mq_open(“SERVIDOR_SUMA”, O_WRONLY);
/* se rellena la petición */
pet.a = 5; pet.b = 2; strcpy(pet.q_name,
“CLIENTE_UNO”);
mq_close(q_servidor);
mq_close(q_cliente);
mq_unlink(“CLIENTE_UNO”);
} 43
Ejemplo II: Servidor concurrente
Máquina A
sumar(5,2)
cliente
Resultado = 7
Máquina B
servidor
NÚCLEO
RED
5+2
Máquina A
cliente NÚCLEO
NÚCLEO
44
Estructura de u n servidor multihread
Proceso cliente Proceso cliente
petición
Proceso servidor
Creación del
thread
Creación del
thread
45
Cliente-servidor con colas de mensajes
46
Servidor multithread con colas de mensajes
(I)
#include “mensaje.h”
#include <mqueue.h>
#include
<pthread.h>
#include <stdio.h>
47
Servidor multithread con colas de mensajes
(II)
q_servidor = mq_open(“SERVIDOR”, O_CREAT|O_RDONLY,
0700, &attr);
if (q_servidor == -1) {
perror(”No se puede crear la cola de servidor”);
return 1;
}
pthread_mutex_init(&mutex_mensaje, NULL);
pthread_cond_init(&cond_mensaje, NULL);
pthread_attr_init(&attr);
…..
48
Servidor multithread con colas de mensajes
(III)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
}
}
49
Servidor multithread con colas de mensajes
(IV)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
C ondición de
carrera
}
}
50
Servidor multithread con colas de mensajes
(V)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
} /* FIN while */
} /* Fin main */
51
Servidor multithread con colas de mensajes
(VI)
void tratar_mensaje(struct mensaje *mes){
struct peticion mensaje; /* mensaje local */
struct mqd_t q_cliente; /* cola del cliente */
int resultado; /* resultado de la operación */
pthread_cond_signal(&cond_mensaje);
pthread_mutex_unlock(&mutex_mensaje);
52
Servidor multithread con colas de mensajes
(VII)
/* ejecutar la petición del cliente y preparar respuesta */
resultado = mensaje_local.a + mensaje_local.b;
if (q_cliente == -1)
perror(”No se puede abrir la cola del cliente */
else {
mq_send(q_cliente, (char *) &resultado,
sizeof(int), 0); mq_close(q_cliente);
}
pthread_exit(0);
}
53
Proceso cliente
#include “mensaje.h”
#include <mqueue.h>
void main(void) {
mqd_t
q_servidor;
mqd_t /*
q_cliente; /* cola de mensajes para el proceso cliente */
cola de mensajes
struct peticion pet;
del proceso
int res;
servidor */
struct mq_attr attr;
attr.mq_maxmsg = 1;
attr.mq_msgsize = sizeof(int);
q_cliente =
mq_open(“CLIENTE_UNO”,
O_CREAT|O_RDONLY, 0700,
&attr);
q_servidor =
mq_open(“SERVIDOR_SUMA”,
O_WRONLY);
/* se rellena la petición */
pet.a = 5; pet.b =
2;
strcpy(pet.q_name,
“CLIENTE_UNO”);
Elementos solicitud:
solicitud - <mandato> <dirección documento> <versión HTTP
>
- cabecera opcional
- datos opcionales
respuesta Elementos respuesta:
- línea de estado con formato <protocolo><códigos
estado><descripción>
- información de cabecera
- documento.
56
Protocolo HTTP: respuesta
C ontenido de la respuesta:
<protocolo> <código>
<cabeceras>
<recurso>
58