You are on page 1of 55

Tema 4

El paradigma cliente-servidor
F. García-Carballeira, Mª. Soledad Escolar,
Luis Miguel Sánchez, Fco. Javier García
Sistemas Distribuidos
Grado en Ingeniería Informática
Universidad Carlos III de Madrid

Contenido  

Conceptos básicos
Tipo de servidores    

Sesión:  

interacción entre cliente y servidor

Ejemplo:  

Servidores secuenciales y concurrentes
Servidores orientados a conexión y sin conexión
Servidores con/sin información de estado

Cliente-servidor con paso de mensajes

Guía de desarrollo de aplicaciones cliente-servidor
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

2

Una definición simple …

“El software del servidor acepta peticiones de
servicio desde el software del cliente, calcula el
resultado y lo devuelve al cliente”

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

3

Participantes 

Elementos de computación:   

Cliente
Servidor
Red de interconexión
1) Petición
Red de interconexión
2) Respuesta

Máquina
cliente

Máquina del
servidor

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

4

Ejemplo: HTTP
1) Petición:
http://www.arcos.inf.uc3m.es

2) Respuesta

Cliente
1)

Petición:

Servidor
2)

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: nombre-cliente
[Línea en blanco]

Respuesta:
HTTP/1.1 200 OK
Date: Fri, 31 Dec 2003 23:59:59 GMT
Content-Type: text/html
Content-Length: 1221
<html>
<body>
<h1>Página www.uc3m.es</h1>
(Contenido) . . .
</body>
</html>

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

5

Acceso distribuido vs.
computación distribuida

La computación de tipo cliente-servidor
es acceso distribuido
no computación distribuida !!!

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

6

Cliente-Servidor 

Asigna roles diferentes a los procesos que comunican: cliente y servidor 

Servidor: 
Ofrece un servicio 
Elemento pasivo: espera la llegada de peticiones 

Cliente: 
Solicita el servicio 
Elemento activo: invoca peticiones

...

Servidor

7

Cliente 1

Cliente 2

Petición de servicio
Proceso cliente
Proceso servidor
Servicio

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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, CORBA, …).
Paradigma principalmente adecuado para servicios
centralizados
Ejemplos: servicios de Internet (HTTP, FTP, DNS, … )     

8

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Tipos de servidores de aplicaciones 

En función del número de peticiones que es capaz de atender:   

En función de si existe una conexión preestablecida con el cliente   

Secuencial: una petición
Concurrente: múltiples peticiones atendidas al mismo tiempo

Servidores orientados a conexión
Servidores NO orientados a conexión

En función de si almacena o no el estado de la comunicación  

Servidores con estado
Servidores sin estado

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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

servidor

Cliente

respuesta

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

10

Flujo de ejecución de un servidor
secuencial

Inicio de servicio

Aceptar petición de
sesión

Procesar la petición del
cliente

Servidor secuencial
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

11

Flujo de ejecución de un servidor
secuencial

Inicio de servicio

Aceptar petición de
sesión

Obtener el
resultado
+
Devolver la
respuesta al cliente

Procesar la petición del
cliente

Servidor secuencial
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

12

Cliente-Servidor secuencial
Servidor

while(){
aceptar_peticion()
tratar_peticion()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Cliente n

13

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Sesión de
servicio

Cliente-Servidor secuencial
Servidor

while(){
aceptar_peticion()
tratar_peticion()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Cliente n

14

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Sesión de
servicio

Cliente-Servidor secuencial
Servidor

while(){
aceptar_peticion()
tratar_peticion()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Cliente n

15

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Sesión de
servicio

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
respuesta

Proceso
hijo

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

16

Flujo de ejecución de un servidor
concurrente
Servidor concurrente
Inicio de servicio
Aceptar petición de
sesión
Crear thread
Trabajador 1

Procesar la petición
del cliente 1

fin

Crear thread
Trabajador 2

Procesar la petición
del cliente 2

fin

Crear thread
Trabajador n

Procesar la petición
del cliente n

fin

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

17

Flujo de ejecución de un servidor
concurrente
Servidor concurrente
Obtener el
resultado
+
Devolver la
respuesta al cliente

Inicio de servicio
Aceptar petición de
sesión
Crear thread
Trabajador 1

Procesar la petición
del cliente 1

fin

Crear thread
Trabajador 2

Procesar la petición
del cliente 2

fin

Crear thread
Trabajador n

Procesar la petición
del cliente n

fin

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

18

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Cliente n

19

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Cliente n

20

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

21

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

22

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

Hilo 2

23

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

Hilo 2

24

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

Hilo 2
Hilo n

25

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Cliente-Servidor concurrente
Servidor

while(){
aceptar_peticion()
pthread_create()
}

Cliente 1

Solicitud de
conexión
Cliente 2

Sesión de
servicio

Hilo 1
Cliente n

Hilo 2
Hilo n

26

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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

E/S

Solicitudes

Núcleo

Núcleo

E/S

Núcleo

E/S

Solicitudes

Trabajador

Distribuidor

Solicitudes 

@Fuente: Jesús Carretero, Félix García, Pedro de Miguel y Fernando Pérez. Mc Graw Hill

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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  

Los datos no incluyen información sobre la conexión
establecida  

El flujo de tráfico se representa mediante un identificador de
conexión

Direcciones origen y destino

Ejemplo: TCP

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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  

No existe acuerdo previo

Ejemplo: IP, UDP

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

29

Concepto de sesión  

Sesión: Interacción entre cliente y servidor
Cada 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

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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

Definición del protocolo de servicio:   

Localización del servicio
Secuencia de comunicación entre procesos
Representación en interpretación de los datos
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

31

Tipos de servidores 

Servidores sin estado:   

Cada mensaje de petición y respuesta es independiente de las
demás
Ejemplo: HTTP

Servidores con estado:   

Debe mantener información de estado (por ej. anteriores
conexiones de clientes) para proporcionar su servicio
Cada petición/respuesta puede depender de otras anteriores
Ejemplo: Telnet

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

32

Información de estado 

Información de estado global   

El servidor mantiene información para todos los clientes
durante la vida del servidor
Ejemplo: servidor de tiempo

Información de estado de sesión  

El servidor mantiene información específica para cada sesión
iniciada por los clientes
Ejemplo: FTP (File Transfer Protocol)

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

33

Arquitectura de SW 

La arquitectura de SW de una aplicación cliente-servidor
consta de tres niveles:   

34

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

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

Arquitectura de las aplicaciones

Interfaz de usuario
Lógica de presentación
Lógica de aplicación
Lógica de servicio

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

35

¿Donde se ejecutan las tareas?  

En el software del cliente (lado del cliente)
En el software del servidor (lado del servidor)

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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]

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

37

Responsabilidades en el servidor 

Servidor:
Espera conexiones entrantes de los clientes

1. 

Una conexión entrante es una petición de servicio

Por cada conexión:

2.  

Genera un thread de servicio [Solo servidores concurrentes]
El proceso principal:  

Vuelve a esperar por nuevas conexiones entrantes

El thread de servicio:
1.
2.
3.
4.

Procesa la petición
Calcula el resultado
Devuelve la respuesta al cliente
Finaliza su ejecución

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

38

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    

Una vez finalizada la sesión con el cliente, el proceso ligero se destruye

Modelo concurrente:  

Procesa la petición
Envía la respuesta al servidor

Los procesos distribuidor y trabajador ejecutan de forma concurrente

Modelo secuencial: 

Sólo un proceso distribuidor

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

39

Ejemplo: sumar dos números

Máquina A
cliente

Máquina B
sumar(5,2)

servidor
5+2

NÚCLEO

Resultado = 7

NÚCLEO

@Fuente: Jesús Carretero, Félix García, Pedro de Miguel y Fernando Pérez. Mc Graw Hill

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

RED

40

Ejemplo: Definición de tipos
#define MAXSIZE
struct peticion

256
{

int a;

/* operando 1 */

int b;

/* operando 2 */

char q_name[MAXSIZE];

/* nombre de la cola cliente
donde debe enviar la respuesta
el servidor */

};

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

41

Ejemplo: Proceso servidor secuencial
#include “mensaje.h”
#include <mqueue.h>
void main(void) {
mqd_t q_servidor;
mqd_t q_cliente;
struct peticion pet;
int res;
struct mq_attr attr;

/* cola de mensajes del servidor */
/* cola de mensajes del cliente */

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;
/* se responde al cliente abriendo previamente su cola */
q_cliente = mq_open(pet.q_name, O_WRONLY);
mq_send(q_cliente, &res, sizeof(int), 0);
mq_close(q_cliente);
}
}
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

42

Ejemplo: Proceso cliente
#include “mensaje.h”
#include <mqueue.h>
void main(void) {
mqd_t q_servidor;
mqd_t q_cliente;
struct peticion pet;
int res;
struct mq_attr attr;

/* cola de mensajes del proceso servidor */
/* cola de mensajes para el proceso cliente */

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_send(q_servidor, &pet, sizeof(struct petiticion), 0);
mq_receive(q_cliente, &res, sizeof(int), 0);
mq_close(q_servidor);
mq_close(q_cliente);
mq_unlink(“CLIENTE_UNO”);
}
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

43

Ejemplo II: Servidor concurrente
Máquina A
cliente

sumar(5,2)
Resultado = 7
Máquina B

NÚCLEO

servidor
RED

5+2

Máquina A
cliente

NÚCLEO

NÚCLEO
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

44

Estructura de un servidor multihread
Proceso cliente

Proceso cliente

Cola del
cliente

Cola del
cliente

petición

petición

Proceso servidor
respuesta

Cola del
servidor

respuesta
Creación del
thread

Creación del
thread

Thread que
sirve la petición

Thread que
sirve la petición

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

45

Cliente-servidor con colas de mensajes
Proceso cliente
Cola del
cliente

petición

Proceso servidor
mensaje
respuesta
Proceso
ligero
principal

while (1)
{
mq_receive
se crea el proceso ligero
esperar la copia del mensaje
}

Copia del
mensaje
Copia el mensaje
despierta al principal
continua la ejecución
responde al cliente

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

46

Servidor multithread con colas de mensajes
(I)
#include “mensaje.h”
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
/* mutex y variables condicionales para proteger la copia del mensaje*/
pthread_mutex_t mutex_mensaje;
int mensaje_no_copiado = TRUE;

/* TRUE con valor a 1 */

pthread_cond_t cond_mensaje;
int main(void)
{
mqd_t q_servidor;

/* cola del servidor */

struct peticion mess;

/* mensaje a recibir */

struct mq_attr q_attr;

/* atributos de la cola */

pthread_attr_t t_attr;

/* atributos de los threads */

attr.mq_maxmsg = 20;
attr.mq_msgsize = sizeof(struct peticion));
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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);
/* atributos de los threads */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
…..

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

48

Servidor multithread con colas de mensajes
(III)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
pthread_create(&thid, &attr, tratar_mensaje, &mess);

}
}

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

49

Servidor multithread con colas de mensajes
(IV)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
pthread_create(&thid, &attr, tratar_mensaje, &mess);

Condición de carrera
}
}

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

50

Servidor multithread con colas de mensajes
(V)
while (TRUE) {
mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0);
pthread_create(&thid, &attr, tratar_mensaje, &mess);

Sección crítica
/* se espera a que el thread copie el mensaje */
pthread_mutex_lock(&mutex_mensaje);
while (mensaje_no_copiado)
pthread_cond_wait(&cond_mensaje, &mutex_mensaje);
mensaje_no_copiado = TRUE;
pthread_mutex_unlock(&mutex_mensaje);
}

/* FIN while */

} /* Fin main */

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

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 */
/* el thread copia el mensaje a un mensaje local */
pthread_mutex_lock(&mutex_mensaje);
memcpy((char *) &mensaje, (char *)&mes, sizeof(struct
peticion));
/* ya se puede despertar al servidor*/
mensaje_no_copiado = FALSE;
/* FALSE con valor 0 */
pthread_cond_signal(&cond_mensaje);
pthread_mutex_unlock(&mutex_mensaje);

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

52

Servidor multithread con colas de mensajes
(VII)
/* ejecutar la petición del cliente y preparar respuesta */
resultado = mensaje_local.a + mensaje_local.b;
/* Se devuelve el resultado al cliente */
/* Para ello se envía el resultado a su cola */
q_cliente = mq_open(mensaje_local.nombre, O_WRONLY);
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);
}
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

53

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_send(q_servidor, &pet, sizeof(struct petiticion), 0);
mq_receive(q_cliente, &res, sizeof(int), 0);
mq_close(q_servidor);
mq_close(q_cliente);
mq_unlink(“CLIENTE_UNO”);
}

F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García
Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

54

Guía de desarrollo de aplicaciones
cliente-servidor con paso de mensajes
1.

Identificar el cliente y el servidor
Cliente: elemento activo, varios
Servidor: elemento pasivo  

2.

Protocolo del servicio
Identificar los tipos mensajes y la secuencia de intercambios de
mensajes (peticiones y respuestas) 

3.

Elegir el tipo de servidor
UDP sin conexión
TCP :    

4.

Una conexión por sesión
Una conexión por petición

Identificar el formato de los mensajes (representación de los
datos) 

Independencia (lenguaje, arquitectura, implementación, …)
F. García-Carballeira, Mª. Soledad Escolar, Luis Miguel Sánchez, Fco. Javier García

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0 España.

55