Tema 5 Comunicación con socketsocw.uc3m.es/.../Tema5_sockets.pdf · Cada socket debe tener...

Post on 03-Aug-2020

9 views 0 download

Transcript of Tema 5 Comunicación con socketsocw.uc3m.es/.../Tema5_sockets.pdf · Cada socket debe tener...

Tema 5

Comunicación con socketsF. 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 sobre sockets

� Modelo de comunicación

� Sockets

� Datagrama

� Stream

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.

Stream

� API de programación

� Sockets en C

� Sockets en Java

� Guía de diseño de aplicaciones cliente-servidor

2

Sockets: introducción

� Mecanismo de IPC que proporciona comunicación entre procesos que ejecutan en máquinas distintas

� Aparecieron en 1981 en UNIX BSD 4.2

� Intento de incluir TCP/IP en UNIX

� Diseño independiente del protocolo de comunicación

� Un socket es un descriptor de un punto final de comunicación (direcció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.

3

� Un socket es un descriptor de un punto final de comunicación (dirección IP y puerto)

� Abstracción que:

� Representa un extremo de una comunicación bidireccional con una dirección asociada

� Ofrece interfaz de acceso a los servicios de red en el nivel de transporte

� Protocolo TCP y UDP

Sockets: introducción

RMI and RPC

Sockets

Aplicaciones/servicios

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

Aplanamiento (marshalling), representación externa

de datos

Protocolo de transporte

UDP y TCP

Sockets: introducción

� Sujetos a proceso de estandarización dentro de POSIX(POSIX 1003.1g)

� Actualmente disponibles en:

� Casi todos los sistemas UNIX

� Prácticamente todos los sistemas operativos

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

� WinSock: API de sockets de Windows

� Macintosh

� En Java como clase nativa

Sockets UNIX

� Dominios de comunicación

� AF_UNIX

� AF_INET

� Tipos de sockets

� Stream (SOCK_STREAM)

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

� Datragrama (SOCK_DGRAM)

� Direcciones de sockets

Dominios de comunicación

� Un dominio representa una familia de protocolos

� Un socket está asociado a un dominio desde su creación

� Sólo se pueden comunicar sockets del mismo dominio

� Los servicios de sockets son independientes del dominio

� Ejemplos de dominios:

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.

7

� Ejemplos de dominios:

� AF_UNIX (o AF_LOCAL): comunicación dentro de una máquina

� AF_INET: comunicación usando protocolos TCP/IP

Tipos de sockets

� Stream (SOCK_STREAM)� Protocolo TCP

� Datagrama (SOCK_DGRAM)� Protocolo 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.

8

� Raw (SOCK_RAW)� Sockets sin protocolo de transporte

Sockets stream

� Protocolo TCP (RFC 793)

� Flujo de datos bidireccional

� Orientado a conexión� Debe establecerse una conexión extremo-a-extremo antes del envío y recepción de datos

� Proporcionan fiabilidad

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

� Proporcionan fiabilidad� Paquetes ordenados por secuencia, sin duplicación de paquetes, libre de errores

� Ejemplos:� HTTP, Telnet, FTP, SMTP

Sockets datagrama

� Protocolo UDP (RFC 768)� Flujo de datos bidireccional� No orientado a conexión

� No se establece/mantiene una conexión entre los procesos que comunican

� Un datagrama es una entidad autocontenida

� Longitud máxima de un datagrama (datos y cabeceras) es 64

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

� Longitud máxima de un datagrama (datos y cabeceras) es 64 KB

� Mantiene separación entre paquetes

� No proporcionan fiabilidad� Paquetes desordenados, duplicados, pérdidas

� Ejemplos:� DNS

Sockets: stream y datagramas

Process AsocketAPI runtime

support

Process Bsocket

API runtimesupport

transport layer software transport layer software

a datagrama logical connection created and maintained

connectionlessdatagram socket

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

a logical connection created and maintainedby the runtime support of the datagramsocket API

Process AsocketAPI runtime

support

Process Bsocket

API runtimesupport

transport layer software transport layer software

connection-oriented datagram socket

Correspondencia entre familia y tipos de

sockets

TIPO SOCKET AF_UNIX AF_INET

SOCK_STREAM Yes TCP

SOCK_DGRAM Yes UDP

SOCK_RAW IP

SOCK_SEQPACKT

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

FAMILIA TIPO Protocolo Protocolo actual

AF_INET SOCK_DGRAM IPPROTO_UDP UDP

AF_INET SOCK_STREAM IPPROTO_TCP TCP

AF_INET SOCK_RAW IPPROTO_ICMP ICMP

AF_INET SOCK_RAW IPPROTO_RAW raw

Direcciones de sockets

� Cada socket debe tener asignada una dirección única

� Dirección de host (32 bits) + puerto (16 bits) + protocolo

� Las direcciones se usan para:

� Asignar una dirección local a un socket (bind)

� Especificar una dirección remota (connect o sendto)

Las direcciones son dependientes del dominio

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.

13

� Las direcciones son dependientes del dominio

� Se utiliza la estructura genérica struct sockaddr

� Cada dominio usa una estructura específica

� Direcciones en AF_UNIX (struct sockaddr_un)

� Nombre de fichero

� Direcciones en AF_INET(struct sockaddr_in)

� Es necesario la conversión de tipos (casting) en las llamadas

Puertos� Un puerto identifica un destino en un computador

� Los puertos se asocian a procesos, � permiten que la transmisión se dirija a un proceso específico en el computador destino

� Un puerto tiene un único receptor y múltiples emisores (excepto multicast)

� Toda aplicación que desee enviar y recibir datos debe abrir un puerto

� Número entero de 16 bits � 2^16 puertos en una máquina ~ 65536 puertos posibles

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.

14

� 2^16 puertos en una máquina ~ 65536 puertos posibles� Reservados por la IANA para aplicaciones de Internet: 0-1023 (también llamados well-known puertos)

� Puertos entre 1024 y 49151 son puertos registrados para ser usados por los servicios

� Puertos por encima de 65535 para uso privado

� El espacio de puertos para streams y datagramas es independiente� http://www.iana.org/assignments/port-numbers

� Protocolo

� TCP, UDP

� Dirección IP local (origen)

� Puerto local (origen)

� Dirección IP remota (destino)

Información asociada a una

comunicació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.

� Dirección IP remota (destino)

� Puerto remoto (destino)

(Protocolo, IP-local, P-local, IP-remoto, P-remoto)

15

Encapsulación de un paquete TCP

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.

16

Encapsulación de un paquete TCP

Datos

DatosCabeceraTCP

Puerto Origen

Puerto Destino

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

Encapsulación de un paquete TCP

Datos

Datos

Puerto Origen

Puerto Destino

Protocolo =TCP

IP Origen

CabeceraTCP

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

DatosCabeceraTCP

CabeceraIP

IP Origen

IP Destino

Encapsulación de un paquete TCP

Datos

Datos

Puerto Origen

Puerto Destino

Protocolo =TCP

IP Origen

CabeceraTCP

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.

19

DatosCabecera

TCPCabecera

IPCabeceraEthernet

ColaEthernet

Tipo de trama = IP

Dirección Eth. Origen

Dirección Eth. Destino

DatosCabeceraTCP

CabeceraIP

IP Origen

IP Destino

Direcciones IP

� Una dirección IP se almacena en una estructura de tipo in_addr

#include <netinet/in.h>

typedef uint32_t in_addr_t ;

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.

20

typedef uint32_t in_addr_t ;

struct in_addr

{

in_addr_t s_addr;

};

Direcciones de sockets en AF_INET

� Estructura struct sockaddr_in� Debe iniciarse a 0 � La estructura tiene tres campos importantes

� sin_family: dominio (AF_INET)� sin_port: puerto

� sin_addr: dirección del host

family

2-byte port

struct sockaddr_in

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.

#include <netinet/in.h>struct sockaddr_in {

short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero[8];

};

21

4-byte Net ID, host ID

unused

Direcciones de sockets en AF_UNIX

� La estructura struct sockaddr_un describe la dirección de un socket AF_LOCAL o AF_UNIX

#include <sys/un.h>

struct sockaddr_un { family

struct sockaddr_un

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.

22

{

short sun_family;

char sun_path[108];

};

familyPathname

(up to 108 bytes)

Servicios sobre direcciones

� Obtener el nombre de un host

� Transformar direcciones

� Obtener la dirección de un host

� Representación de datos

� Interna

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.

� Interna

� Externa

23

Obtener el nombre de un host

� Función que facilita el nombre de la máquina en la que se ejecuta:

int gethostname (char *name, size_t namelen);

donde:

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.

donde:

name referencia al buffer donde se almacena el

nombre

namelen longitud del buffer

24

Ejemplo I: obtener nombre host#include <unistd.h>

void main (){

char maquina[256];int err;

err = gethostname( maquina , 256);

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.

err = gethostname( maquina , 256);

printf (“Ejecuto en la maquina %s\n”, maquina);

exit(0);}

25

Transformación de direcciones

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.

26

The McGraw-Hill

Obtención de la dirección de host

� Usuarios manejan direcciones en forma de texto:� Notación decimal-punto (ej: 138.100.8.100)� Notación dominio-punto (ej. www.uc3m.es)

� Dos funciones de transformación de direcciones:� Devuelve una dirección IP en notación decimal-punto

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.

char * inet_ntoa (struct in_addr in);

� Obtiene una dirección IP a partir de notación decimal punto

int inet_aton (const char *cp, struct in_addr *in);

27

Ejemplo II:

transformación de direcciones#include <netdb.h>#include <stdio.h>

void main (int argc, char **argv){struct in_addr in;

if (argc != 2) {printf ("Uso: %s <decimal-punto>\n", argv[0]);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.

28

}if ( inet_aton(argv[1], &in) == 0) {

printf("Error en la dirección\n");exit(0);

}

printf ("La dirección es %s\n", inet_ntoa(in));

exit(0 );}

Obtener la dirección de host

� Obtiene la información de un host a partir de una dirección en formato dominio-punto

struct hostent * gethostbyname (char *str);

Argumentos:

str es el nombre de la máquina

� Obtiene la información de un host a partir de una dirección IP

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.

� Obtiene la información de un host a partir de una dirección IP

struct hostent * gethostbyaddr (void *addr, int len, int type);

Argumentos:

addr es un puntero a una estructura de tipo struct in_addr

len es el tamaño de la estructura

type es AF_INET

29

Estructura hostent

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

The McGraw-Hill

Ejemplo III: obtener la dirección de host en dominio-punto

#include <netdb.h>

#include <stdio.h>#include <string.h>

void main(int argc, char **argv) {

struct hostent *hp;struct in_addr in;

hp = gethostbyname(“www.uc3m.es”);

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.

if (hp == NULL) {printf (“Error en gethostbyname\n”);exit(0);

}memcpy(&in.s_addr,*(hp->h_addr_list),sizeof(in.s_addr));

printf (“%s es %s\n”, hp->h_name, inet_ntoa(in));}

31

#include <netdb.h>#include <stdio.h>#include <string.h>

main (int argc, const char **argv){

u_int addr; struct hostent *hp;char **p; struct in_addr in;char **q;

Ejemplo IV:obtener la dirección de host en decimal-punto

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.

if (argc != 2) {printf("USO: %s Direccion-IP\n", argv[0]);

exit (1);}

err = inet_aton(argv[1], &addr);

if (err == 0) {printf("Direccion IP en formato a.b.c.d\n");exit (2);

}

32

hp=gethostbyaddr((char *) &addr, sizeof (addr), AF_INET);

if (hp == NULL) {

printf(“Error en ....\”n);

exit (3);

}

for (p = hp->h_addr_list; *p!=0;p++){

Ejemplo IV:obtener la dirección de host en decimal-punto

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

memcpy(&in.s_addr, *p, sizeof(in.s_addr));

printf("%s\t%s", inet_ntoa(in), hp->h_name);

for (q=hp->h_aliases;*q != 0; q++)

printf("%s\n", *q);

}

exit(0);

}

Orden de los bytes

� Big-endian es el estándar para el ordenamiento de los bytes usado en TCP/IP

� También llamado Network byte order

� Big-endian

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.

� Little-endian

34

� Big Endian

1

Ejemplo: Representación del 1

0 0 0

n n+1 n+2 n+3Direcciones:

LSBMSB

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.

� Little Endian

35

01 0 0

LSBMSB

Dirección de crecimiento

n+3 n+2 n+1 nDirecciones:

Dirección de crecimiento

Representación de datos

� Empaquetamiento de datos (marshalling):� Serialización de las estructuras de datos y conversión de los valores de los datos

a su representación externa

-1.5“Esto es una cadena” 1.2 7.3

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.

� Desempaquetamiento de datos (unmarshalling)� Conversión de los datos a su representación interna

36

…10010111…0110010…

-1.5“Esto es una cadena” 1.2 7.3

Representación en el computador A

Representación en el computador B

Funciones de transformación:

network �� host

� En computadores que no utilicen Big-endian es necesario emplear funciones para traducir números entre el formato que utiliza TCP/IP (Big-endian) y el empleado por el propio computador (Little-endian) :

� Host (Little-Endian) � Network (Big-Endian)

Traduce un número de 32/16 bits representado en el formato del computador al formato de red (TCP/IP)

u_long htonl ( u_long hostlong )

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

u_long htonl ( u_long hostlong ) u_short htons (u_short hostshort)

� Network (Big-Endian) � host (Little-Endian)

Traduce un número de 32/16 bits representado en el formato de red (TCP/IP) al formato del computador

u_long ntohl (u_long netlong)u_short ntohs (u_short netshort)

Funciones de transformació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

The McGraw-Hill

Modelos de comunicación

� Sockets stream (SOCK_STREAM)

� Orientado a conexión

� TCP

� Sockets datagrama (SOCK_DGRAM)

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.

� Sockets datagrama (SOCK_DGRAM)

� No orientado a conexión

� UDP

39

Modelo de comunicación con sockets

stream

Proceso cliente

Proceso servidor

socket()

socket()

bind()

listen()

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.

40

accept()

read()

close()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

Conexión

Modelo de comunicación con sockets

datagrama

Proceso cliente

Proceso servidor

socket()

socket()

bind()

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

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

Primitivas POSIX

para la gestión de sockets

� Creación de un socket (socket)

� Asignación de direcciones (bind)

� Preparar para aceptar conexiones (listen)

� Aceptar una conexión (accept)

� Solicitud de conexión (connect)

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.

� Solicitud de conexión (connect)

� Obtener la dirección de un socket

� Transferencia de datos� Streams

� Datagramas

� Cerrar un socket (close)

42

Creación de un socket (socket)� Crear un socket:

#include <sys/types.h>#include <sys/socket.h>int socket(int dominio, int tipo, int protocolo)

Argumentos:dominio AF_UNIX,AF_INETtipo SOCK_STREAM,SOCK_DGRAMprotocolo dependiente del dominio y tipo

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

protocolo dependiente del dominio y tipo� 0 elige el más adecuado� Especificados en /etc/protocols

devuelve: si éxito, un descriptor de socketsi error, -1

� El socket creado no tiene dirección asignada

Ejemplo V: Crear un socket#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#define TCP 6#define UDP 17 /* ver /etc/protocols */int main (){

/* VARIABLES DEL PROGRAMA */

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.

/* VARIABLES DEL PROGRAMA */int sockfd;

if ((sockfd= socket(AF_INET, SOCK_STREAM, TCP))==-1){

printf (“Error en la creación del socket”);exit(-1);

}/* CONTINUACIÓN DEL PROGRAMA */

}

44

Asignación de direcciones (bind)� Asignar dirección a un socket:

#include <sys/types.h>#include <sys/socket.h>

int bind (int sd, struct sockaddr *dir, int long)

Argumentos:sd descriptor devuelto por socketdir dirección a asignarlong longitud de la dirección/tamaño de la estructura sockaddr

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

long longitud de la dirección/tamaño de la estructura sockaddr

devuelve –1 si error y 0 si se ejecutó con éxito

� Direcciones en dominio AF_INET (struct sockaddr_in)� Host: una dirección local IP

� INNADDR_ANY: elige cualquiera de la máquina

� Puertos: � 65535 puertos disponibles, de los cuales 0..1023 están reservados� Si 0, el sistema elige uno

� Si no se asigna dirección al socket (típico en clientes)� Se le asigna automáticamente (puerto efímero) en la primera utilización (connect o sendto)

Obtener la dirección de un socket

� Obtener la dirección a partir del descriptor:

int getsockname (int sd, struct sockaddr *dir, int *long)

sd descriptor devuelto por socket

dir dirección del socket devuelta

long parámetro valor-resultado

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

� Obtener la dirección del socket en el otro extremo de la conexión:

int getpeername (int sd, struct sockaddr *dir, int *long)

sd descriptor devuelto por socket

dir dirección del socket remoto

long parámetro valor-resultado

Preparar para aceptar conexiones (listen)

� Habilita un socket para recibir conexiones en el servidor TCP

� Realizada en el servidor stream después de socket y bind#include <sys/types.h>

#include <sys/socket.h>

int listen( int sd, int baklog)

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

Argumentos:

sd: descriptor devuelto por socket

backlog: número máximo de peticiones que se encolarán (algunos manuales recomiendan 5)

antes de ejecutar accept

devuelve –1 si error y 0 si se ejecutó con éxito

Aceptar una conexión (accept)

� Realizada en el servidor stream después de socket, bind y listen

� Bloquea al servidor hasta que se produce la conexión; el servidor obtiene:

� La dirección del socket del cliente

� Un nuevo descriptor que queda conectado al socket del 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.

48

� Un nuevo descriptor que queda conectado al socket del cliente

� Después de la conexión quedan activos dos sockets en el servidor:

� El original para aceptar nuevas conexiones

� El nuevo para enviar/recibir datos por la conexión establecida

Aceptar una conexión (accept)#include <sys/types.h>

#include <sys/socket.h>

int accept (int sd, struct sockaddr *dir, int *long)

Argumentos:sd descriptor devuelto por socket

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

sd descriptor devuelto por socket

dir dirección del socket del cliente

long parámetro valor-resultado:1) Antes de la llamada: tamaño de dir

2) Después de la llamada: tamaño de la dirección del cliente

que se devuelve

� Devuelve un nuevo descriptor de socket asociado a la conexión

� -1 en caso de error

Solicitud de conexión (connect)

� Realizada en el cliente stream para conectarse al servidor

#include <sys/types.h>#include <sys/socket.h>int connect (int sd, struct sockaddr *dir, int long)

Argumentos:

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.

Argumentos:sd descriptor devuelto por socketdir dirección del socket remoto

long longitud de la dirección

devuelve –1 si error y 0 si se ejecutó con éxito

� Si el socket no tiene dirección asignada, se le asigna una automáticamente

50

Establecimiento de una conexión en 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.

51

@Fuente : James F. Kurose, Keith W. Ross Computer Networking: A Top-Down Approach

Ejemplo VI: Establecimiento de

conexión TCP (clientes)int main (){

int sockfd;struct sockaddr_in server;

if ((sockfd= socket(AF_INET, SOCK_STREAM, 0))==-1){printf (“Error en la creación del socket”);exit(-1);

}server.sin_family = AF_INET;

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuesta

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

write()

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.

server.sin_family = AF_INET;server.sin_port = htons (PORT_SERVER);server.sin_addr.s_addr = htonl (IP_SERVER);

if ( connect(sockfd,(struct sockaddr *)&server, sizeof(server)) <0) {

printf (“Error en el connect”);exit(-1);

}/* CONTINUACION CODIGO CLIENTE */

}

52

Ejemplo VI: Establecimiento de

conexión TCP (servidores)int main () {

int sd, newsd, size;

struct sockaddr_in server, client;

if ((sd= socket(AF_INET, SOCK_STREAM, 0))==-1){

printf (“Error en la creación del socket”);

exit(-1);

}

server.sin_family = AF_INET;

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

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.

server.sin_family = AF_INET;

server.sin_port = htons (PORT_SERVER);

server.sin_addr.s_addr = htonl (IP_SERVER);

/* bind */

if ( bind(sd,(struct sockaddr *)&server, sizeof(server)) <0) {

printf (“Error en el bind”);

exit(-1);

}

53

Ejemplo VI:

continuación (servidores)

listen(sd,5)

for (;;) {

if ( newsd=accept (sd,(struct sockaddr *) &client, sizeof(client)) < 0) {

printf (“Error en el accept”);

exit(-1);

}

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

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.

/* transferir datos sobre newsd */

….

/* cerrar newsd */

} /* fin for */

/* cerrar sd */

} /* fin main */

54

Transferencia de datos con streams

� Una vez establecida la conexión usando sockets stream, ambos extremos puede transferir datos

� Envío:

int write (int sd, char *mem, int long);

int send (int sd, const void *mem, size_t long, intflags);

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.

� Devuelve el número de bytes enviados o –1 si error� El cuarto parámetro flags permite especificar opciones de envío (man send)

� 0 si no opciones� MSG_OOB|MSG_DONTWAIT|MSG_DONTROUTE

� Pueden no transferirse todos los datos� Es importante comprobar siempre el valor que devuelven estas

llamadas

55

Transferencia de datos con streams

� La recepción es una llamada bloqueante (síncrona)

� Recepción:

int read (int sd, char *mem, int long);int recv (int sd, void *buf,size_t long, int flags);

� Devuelve el número de bytes recibidos o –1 si error� El cuarto parámetro flags permite especificar opciones de recepción (man

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.

� El cuarto parámetro flags permite especificar opciones de recepción (manrecv)� 0 si no opciones� MSG_OOB|MSG_PEEK|MSG_DONTROUTE

� Pueden no transferirse todos los datos� Es importante comprobar siempre el valor que devuelven estas

llamadas

56

Ejemplo VII:

Transferencia de datos con streams

� Función que envía un bloque de datos con reintentos:

int enviar (int socket, char *mensaje, int longitud){

int r;int l = longitud;do {

r = write(socket, mensaje, l);

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.

r = write(socket, mensaje, l);l = l – r;mensaje = mensaje + r;

} while ((l>0) && (r>=0));

if (r < 0)return (-1); /* fallo */

elsereturn (0);

}

57

Transferencia de datos con datagramas� No hay conexión real� Para usar un socket para transferir datos basta con:

� Crearlo (socket)� Asignarle una dirección (bind)

� Si no se le asigna dirección, lo hará el sistema de manera transparente

� Envío:

int sendto (int sd, char *buffer, int long, int flags, struct sockaddr * dir , int addrlen )

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.

struct sockaddr * dir , int addrlen )

� Devuelve el número de bytes enviados o –1 si error� Argumentos:

sd descriptor de socket buffer puntero a los datos a enviarlong la longitud de los datosflags opciones de envío (man sendto)dir dirección del socket remotoaddrlen la longitud de la dirección

58

Transferencia de datos con datagramas� Recepción:

int recvfrom (int sd, char *buffer, int long, int flags, struct sockaddr *dir, int addrlen)

� Devuelve el número de bytes recibidos o –1 si error � Argumentos:

sd descriptor de socket buffer puntero a los datos a enviar

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.

buffer puntero a los datos a enviarlong la longitud de los datosflags opciones de recepción (man recvfrom)dir dirección del socket remotoaddrlen la longitud de la dirección

� Pueden no transferirse todos los datos� Es importante comprobar siempre el valor que devuelven estas

llamadas

59

Cerrar un socket (close)

� Se usa close para cerrar ambos tipos de sockets (stream y datagrama)

int close (int sd);

� Cierra la conexión en ambos sentidos

� Devuelve –1 si error

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.

60

� Se puede cerrar un único extremo:

int shutdown (int sd, int modo);

sd descriptor devuelto por socketmodo SHUT_RD, SHUT_RW o SHUT_RDWR

� Devuelve –1 si error

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, -, -)

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.

61

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, -, -)accept()

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.

62

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, -, -)connect()

accept()

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.

63

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, -, -)connect()

Nuevo descriptor de socket

accept()

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.

64

Nuevo descriptor de socket

fork()

(tcp, host-A, 22, host-B, 1500)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 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.

65

Conexión (tcp, host-A, 22, host-B, 1500)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 22)accept()

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.

66

Conexión (tcp, host-A, 22, host-B, 1500)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 22)accept()

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.

67

Conexión

cliente

(host-C, 4000)

(tcp, host-C, 4000, -, -)

(tcp, host-A, 22, host-B, 1500)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 22)accept()

connect()

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.

68

Conexión

cliente

(host-C, 4000)

(tcp, host-C, 4000, -, -)

(tcp, host-A, 22, host-B, 1500)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 22)accept()

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.

69

Conexión

cliente

(host-C, 4000)

(tcp, host-C, 4000, -, -)

(tcp, host-A, 22, host-B, 1500)

Nuevo descriptor de socket

fork()

(tcp, host-A, 22, host-C, 4000)

Conexión con TCP

Servidor

(host-A, 22)

(tcp, host-A, 22, -, -)

cliente

(host-B, 1500)

(tcp, host-B, 1500, host-A, 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.

70

Conexión

cliente

(host-C, 4000)

(tcp, host-C, 4000, host-A, 22)

(tcp, host-A, 22, host-B, 1500)

(tcp, host-A, 22, host-C, 4000)

Conexión

Configuración de opciones

� Existen varios niveles dependiendo del protocolo afectado como parámetro

� SOL_SOCKET: opciones independientes del protocolo

� IPPROTO_TCP: nivel de protocolo TCP

� IPPTOTO_IP : nivel de protocolo IP

� Consultar opciones asociadas a un socket

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.

� Consultar opciones asociadas a un socketint getsockopt (int sd, int nivel, int opc,

char *val, int *long)

� Modificar las opciones asociadas a un socketint setsockopt (int sd, int nivel, int opc,

char *val, int long)

� Ejemplos (nivel SOL_SOCKET):

� SO_REUSEADDR: permite reutilizar direcciones

71

¿Por qué utilizar SO_REUSEADDR?

� TCP mantiene las conexiones bloqueadas durante un cierto tiempo (TIME_WAIT)

� La conexión ya ha sido cerrada y no puede utilizarse, pero todavía no se han eliminado las tablas internas asociadas por si permanecen todavía segmentos en tránsito en la red

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.

72

permanecen todavía segmentos en tránsito en la red int val = 1;

setsockopt (sd, SOL_SOCKET, SO_REUSEADDR,

(char *) &val, sizeof(int));

SO_RCVBUF, SO_SNDBUF

� Buffer de envío y recepción

� Fijar el tamaño del buffer de envío:

int size = 16384;err = setsockopt (s, SOL_SOCKET, SO_SNDBUF,

(char *)&size, (int)sizeof(size));

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.

73

� Conocer el tamaño del buffer de envío:int size;

err = getsockopt (s, SOL_SOCKET, SO_SNDBUF, (char *)&size,(int)sizeof(size));

printf(“%d\n”, size)

TCP_NODELAY

� Envío inmediato (sin intentar agrupar mensajes relativamente juntos en el tiempo)

int option = 1;

rc = setsockopt (s, IPPROTO_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.

74

TCP_NODELAY,

&option,

sizeof(option));

Sockets de Java

� El paquete java.net de Java permite crear socketsTCP/IP

� Clases para sockets datagrama:

� DatagramSocket

� DatagramPacket

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.

� DatagramPacket

� Clases para sockets stream:

� ServerSocket

� Socket

75

Sockets datagrama

� DatagramPacket:

� Implementa un objeto que permite enviar o recibir paquetes

� Constructor: DatagramPacket

� Métodos: getAddress, getPort, ...

� http://download.oracle.com/javase/6/docs/api/java/net/DatagramPacket.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.

76

� DatagramSocket:

� Implementa un socket que se puede utilizar para enviar o recibir datagramas.

� Constructor: DatagramSocket

� Métodos: send, receive, close, setSoTimetout, getSoTimeout,...

� http://download.oracle.com/javase/6/docs/api/java/net/DatagramSocket.html

Sockets datagrama

Vector de bytes

Dirección delreceptor

Proceso emisor

Vector de bytes

Proceso receptor

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.

77

Objeto DatagramPacket

Objeto DatagramSocket

send

receive

Referencia a objeto

Flujo de datos

Objeto DatagramPacket

Objeto DatagramSocket

Sockets stream� La clase socket implementa un socket stream

� Socket(InetAddress dirección, int puerto)� OutputStream getOutputStream()

� flush

� InputStream getInputStream()� void setSoTimeout(int tiempo_de_espera)� http://download.oracle.com/javase/6/docs/api/java/net/Socket.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.

� La clase ServerSocket implementa un socket a utilizar en los servidores para esperar la conexiones de los clientes� socket accept()� void close()� void setSoTimeout(int tiempo_de_espera)� http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html

78

Ejemplo XI:

Modelo de comunicación

Cliente ServerSocket(puerto);

accept();socket(host, puerto)

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.

79

OutputStream

OutputStream

InputStream

InputStream

close() close()

Guía de diseño de aplicaciones cliente-

servidor

� Modelo de comunicación: conexión/no conexión

� Servidor secuencial/concurrente

� Problemas de concurrencia

� Comunicación síncrona/asíncrona

� Localización:

Dirección IP y puerto en destino

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.

� Dirección IP y puerto en destino

� Formato de los datos

� Orden de los bytes: big-endian/little-endian

� Opciones de los sockets

� Protocolo de servicio

� Fiabilidad: Gestión de errores (UDP)

80

Comparación de protocolos

IP UDP TCP

¿Orientado a conexión? No No Si

¿Límite entre mensajes? Si Si No

¿Ack? No No Si

¿Timeouty retransmisión? No No Si

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.

¿Timeouty retransmisión? No No Si

¿Detección de duplicación? No No Si

¿Secuenciamiento? No No Si

¿Flujo de control? No No Si

81

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

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

petición

respuesta

servidor

82

Ejemplo VIII:

Programar un servidor y cliente en TCP

clientesumar(5,2)

5+2

servidor

Máquina A Máquina B

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.

83

NÚCLEO Resultado = 7 NÚCLEO

RED

Ejemplo VIII: Modelo de comunicación

Proceso cliente

Proceso servidor

socket()

socket()

bind()

listen()

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.

84

accept()

read()

close()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

Conexión

Ejemplo VIII: Servidor TCP#include <sys/types.h>#include <sys/socket.h>

void main (int argc, char *argv[]){struct sockaddr_in server_addr, client_addr;int sd, sc;int size, val;int size;int num[2], res;

if (( sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP ))<0)

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

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.

85

if (( sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP ))<0)printf (“SERVER: Error en el socket”);

val = 1;setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof (int));

bzero ((char *)&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(4200);

bind(sd, &server_addr, sizeof(server_addr));

Ejemplo VIII: Servidor TCP

listen(sd, 5);size = sizeof( client_addr);

while (1) {printf("esperando conexion\n");

sc = accept(sd, (struct sockaddr *)&client_addr,&size);

read ( sc, (char *) num, 2 *sizeof(int)); // recibe la petición

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuestawrite()

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.

86

res = num[0] + num[1]; // procesa la petición

write(sc, &res, sizeof(int)); // envía el resultado

close(sc); // cierra la conexión (sc)}

close (sd);exit (0);

} /*fin main */

Ejemplo VIII: Cliente TCP#include <sys/types.h>#include <sys/socket.h>

void main (int argc, char **argv) // en argv[1] == servidor {

int sd;struct sockaddr_in server_addr;struct hostent *hp;int num[2], res;

if (argc != 2){printf ("Uso: cliente <direccion_servidor > \ n");

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuesta

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

write()

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.

87

printf ("Uso: cliente <direccion_servidor > \ n");exit (0);

}

sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

bzero ((char *)&server_addr, sizeof(server_addr));hp = gethostbyname (argv[1]);

memcpy (&(server_addr.sin_addr), hp->h_addr, hp->h_length) ;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(4200);

Ejemplo VIII: Cliente TCP

// se establece la conexiónconnect(sd, (struct sockaddr *) &server_addr, sizeof(server_ addr));

num[0]=5;num[1]=2;

write(sd, (char *) num, 2 * sizeof (int)); // envía la petición

Proceso cliente

socket()

connect()

read()

close()

Peticiónwrite()

Respuesta

Proceso servidor

socket()

bind()

listen()

accept()

read()

close()

write()

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.

88

read(sd, &res, sizeof (int)); // recibe la respuesta

printf ("Resultado es %d \n", res);

close (sd);exit (0);

} /* fin main */

Ejemplo IX:

Programar un servidor y cliente en UDP

clientesumar(5,2)

5+2

servidor

Máquina A Máquina B

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.

89

NÚCLEO Resultado = 7 NÚCLEO

RED

Ejemplo IX:

Modelo de comunicación

Proceso cliente

Proceso servidor

socket()

socket()

bind()

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.

90

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

Ejemplo IX:

Servidor UDP#include <sys/types.h>

#include <sys/socket.h>

void main (void)

{

int num[2];

int s, res, clilen;

struct sockaddr_in server_addr, client_addr;

Proceso cliente

Proceso servidor

socket()

socket()

bind()

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

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.

91

s = socket(AF_INET, SOCK_DGRAM, 0);

bzero ((char *)&server_addr, sizeof (server_addr));

server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = INADDR_ANY;

server_addr.sin_port = htons(7200);

bind(s, (struct sockaddr *)&server_addr, sizeof (server_addr));

Ejemplo IX:

Servidor UDP

clilen = sizeof (client_addr);

while (1)

{

recvfrom(s, (char *) num, 2* sizeof (int), 0,

(struct sockaddr *)&client_addr, &clilen);

Proceso cliente

Proceso servidor

socket()

socket()

bind()

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

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.

92

res = num[0] + num[1];

sendto(s, (char *)&res, sizeof (int), 0,

(struct sockaddr *)&client_addr, clilen);

}

} /* fin main */

Ejemplo IX:

Cliente UDP

void main (int argc, char *argv[]){

struct sockaddr_in server_addr, client_addr;struct hostent *hp;int s, num[2], res;

if (argc != 2){printf ("Uso: cliente <direccion_servidor> \n");exit (0);

Proceso cliente

Proceso servidor

socket()

socket()

bind()

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

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.

93

exit (0);}

s = socket(AF_INET, SOCK_DGRAM, 0);hp = gethostbyname (argv[1]);

bzero ((char *)&server_addr, sizeof(server_addr));memcpy (&(server_addr.sin_addr), hp->h_addr, hp->h_length) ;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(7200);

Ejemplo IX:

Cliente UDPbzero ((char *)&client_addr, sizeof(client_addr));client_addr.sin_family = AF_INET;client_addr.sin_addr.s_addr = INADDR_ANY;client_addr.sin_port = htons(0);

bind (s, (struct sockaddr *)&client_addr, sizeof (client_addr));

num[0] = 2;num[1] = 5;

Proceso cliente

Proceso servidor

socket()

socket()

bind()

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom() sendto()

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.

94

sendto(s, (char *)num, 2 * sizeof(int), 0, (struct sockaddr *) &server_addr, sizeof (server_addr));

recvfrom(s, (char *)&res, sizeof(int), 0, NULL, NULL);

printf ("2 + 5 = %d\n", res);close(s);

}

Problemas de los ejemplos anteriores

� Comprobación de errores. Muy importante

� Problemas en la transferencia de los datos

� Ordenamiento de los bytes

� ¿Qué ocurre si el cliente es little-endian y el servidor big-endian?

� Hay que resolver el problema de la representación de los datos. Una posibilidad es utilizar las funciones:

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.

95

u_long htonl (u_long hostlong)

u_short htons (u_short hostshort)

u_long ntohl (u_long netlong)

u_short ntohs (u_short netshort)

� Definir el formato de representación e intercambio de datos

� Los datos que se envian a la red deben estar en Network Byte Order

� Los datos que se reciben de la red deben estar en Host Byte Order

Ejemplo X: Programar un servidor y cliente

usando sockets datagramas de Java

clientesumar(5,2)

5+2

servidor

Máquina A Máquina B

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.

96

NÚCLEO

5+2

Resultado = 7 NÚCLEO

RED

Ejemplo X:

Cliente (datagramas)import java.lang.* ;

import java.io.* ;

import java.net.* ;

import java.util.* ;

public class client{

public static void main ( String [] args)

{

byte bsend[] = new byte[100];

byte brecv [] = new byte[100];

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.

97

byte brecv [] = new byte[100];

InetAddress server_addr = null;

DatagramSocket s = null;

DatagramPacket in = null;

DatagramPacket out = null;

int res; int num[] = new int[2];

if (args.length != 1) {

System.out.println("Uso: cliente <host>");

System.exit(0);

}

Ejemplo X:

Cliente (datagramas)try

{

// se crea el socket del cliente

s = new DatagramSocket();

// direción del servidor

server_addr = InetAddress. getByName(args[0]);

num[0] = 2;

num[1] = 5;

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.

98

num[1] = 5;

// empaquetar los datos.

ByteArrayOutputStream baos = new ByteArrayOutputStrea m() ;

ObjectOutputStream dos = new ObjectOutputStream(baos );

dos.writeObject(num);

bsend = baos.toByteArray() ; // se obtiene el buffer (datagrama)

// un único envio

out = new DatagramPacket (bsend, bsend.length, server_addr, 2500);

s. send(out);

Ejemplo X:

Cliente (datagramas)// se recibe el datagrama de respuesta

in = new DatagramPacket (brecv, 100);

s. receive (in);

// se obtiene el buffer

brecv = in. getData ();

// se desempaqueta

ByteArrayInputStream bais = new ByteArrayInputStream( brecv) ;

DataInputStream dis = new DataInputStream ( bais );

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.

99

DataInputStream dis = new DataInputStream ( bais );

res = dis. readInt ();

System.out.println("Datos recibidos " + res);

}

catch (Exception e) {

System.err.println("<<<<<excepcion " + e.toString() );

e.printStackTrace() ;

}

}

}

Ejemplo X:

Servidor (datagramas)

import java.lang.* ;

import java.io.* ;

import java.net.* ;

import java.util.* ;

public class servidor {

public static void main ( String [] args) {

DatagramSocket s = null;

DatagramPacket in, out ;

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.

100

DatagramPacket in, out ;

InetAddress client_addr = null;

int client_port;

byte brecv[] = new byte[100];

byte bsend[] = new byte[100];

int num[], res;

try {

s = new DatagramSocket(2500);

in = new DatagramPacket(brecv, 100); // paquete para recibir la solicitud

Ejemplo X:

Servidor (datagramas)

while (true) {

s. receive(in); //esperamos a recibir

// obtener datos

brecv = in. getData();

client_addr = in.getAddress();

client_port = in.getPort();

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.

101

// desempaquetar los datos

ByteArrayInputStream bais = new ByteArrayInputStream( brecv);

ObjectInputStream dis = new ObjectInputStream(bais);

num = (int[])dis.readObject();

res = num[0] + num[1];

Ejemplo X:

Servidor (datagramas)ByteArrayOutputStream baos = new ByteArrayOutputStre am();

DataOutputStream dos = new DataOutputStream(b aos);

dos.writeInt(res);

bsend = baos.toByteArray();

out = new DatagramPacket ( bsend,

bsend.length,client_addr,

client_port);

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.

102

s. send(out);

}

}

catch(Exception e) {

System.err.println("excepcion " + e.toString() );

e.printStackTrace() ;

}

}

}

Ejemplo XI: Programar un servidor y cliente

usando sockets stream de Java

clientesumar(5,2)

5+2

servidor

Máquina A Máquina B

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.

103

NÚCLEO

5+2

Resultado = 7 NÚCLEO

RED

Ejemplo XI:

Servidor streamimport java.lang.* ;import java.io.* ;import java.net.* ;import java.util.* ;

public class servidor{

public static void main ( String [] args) {

ServerSocket serverAddr = null;Socket sc = null ;

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.

104

Socket sc = null ;int num[] ; // peticiónint res; try {

serverAddr = new ServerSocket(2500);} catch (Exception e){

System.err.println("Error creando socket");}

Ejemplo XI:

Servidor streamwhile (true){

try {

sc = serverAddr. accept(); // esperando conexión

InputStream istream = sc.getInputStream();

ObjectInput in = new ObjectInputStream(istream);

num = (int[]) in. readObject ();

res = num[0] + num[1];

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.

105

DataOutputStream ostream = new DataOutputStream (sc.getOutputStream());

ostream. writeInt (res);

ostream. flush ();

sc. close();

}

catch(Exception e) {

System.err.println("excepcion " + e.toString() );

e.printStackTrace() ;

}

}

}

}

Ejemplo XI:

Cliente streamsimport java.lang.* ;import java.io.* ;import java.net.* ;import java.util.* ;

public class client{

public static void main ( String [] args) {

int res;int num[] = new int [2];

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.

106

int num[] = new int [2];

if (args.length != 1) {System.out.println("Uso: cliente <host>"); System.exit(0);

}try {

// se crea la conexiónString host = args[0];

Socket sc = new Socket(host , 2500); // conexión

Ejemplo XI:

Cliente stream

OutputStream ostream = sc.getOutputStream();ObjectOutput s = new ObjectOutputStream(ost ream);DataInputStream istream = new DataInputStream(sc.getI nputStream());

num[0] = 5; num[1] = 2; //prepara la petición

s. writeObject (num);s. flush ();

res = istream. readInt ();

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.

107

res = istream. readInt ();

sc. close ();System.out.println("La suma es " + res);

} catch (Exception e){

System.err.println("excepcion " + e.toString() );e.printStackTrace() ;

}}

}

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ónservidor

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

respuesta

Crea un procesohijo

Proceso hijo

108

Servidores concurrentes con sockets

stream

Proceso cliente

Proceso servidor

socket()

socket()

bind()

listen()

Abrir 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.

109

accept()

read()

close()

connect()Abrir conexión

read()

close()

Peticiónwrite()

Respuestawrite()

Crear proceso hijo

Modelo de comunicación con sockets

datagrama

Proceso cliente

Proceso servidor

socket()

socket()

bind()

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.

110

recvfrom()

close()close()

Peticiónsendto()

Respuestarecvfrom()

sendto()

Crear proceso hijo

Tipos de servidores concurrentes

� Un proceso servidor concurrente puede crear dos tipos de procesos:

� Procesos convencionales (fork)

� Procesos ligeros (threads)

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.

111

Procesos concurrentes con fork� El servidor crea un socket s y le asocia una dirección� El cuerpo principal del servidor es:

for(;;) {sd = accept(s, (struct sockaddr *)&cliente, &len);

pid = fork(); /* El hijo hereda el descriptor de socket */if (pid == -1)

printf (“Imposible crear mas hijos \ 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.

printf (“Imposible crear mas hijos \ n”);elseif (pid == 0)/* proceso hijo */

{close (s);tratar_peticion(sd);close(sd);exit(0);

}close(sd); /* el padre */

}

112

Procesos concurrentes con fork

� En el modelo anterior el proceso padre no espera la terminación de los procesos hijos con wait

� Los procesos hijos cuando mueren quedan en estado zombie (no desaparecen del sistema)

� Para que los procesos hijos no queden zombies se puede ejecutar en el padre (sólo para UNIX System V):

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.

ejecutar en el padre (sólo para UNIX System V):

signal(SIGCHLD, SIG_IGN);

113

Servidores concurrentes con P. ligeros

Cliente

petcición

Crea thread de servicio

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.

114

respuesta

Thread de servicio

Procesos concurrentes con threads� El servidor crea un socket s y le asocia una dirección� El cuerpo principal del servidor es:

pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

for(;;) {sd = accept(s, (struct sockaddr *)& &cliente, &len);pthread_create(&thid, &attr, tratar_peticion , &sd);

}

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.

� La función que ejecuta el proceso ligero es:

void tratar_peticion (int * s) {int s_local;

s_local = *s;/* tratar la petición utilizando el descriptor de s _local */close(s_local);pthread_exit(NULL);

}

� ¿Es correcta esta solución?

115

Necesario sincronización

� La solución anterior es incorrecta ya que los procesos padre e hijo compiten por el acceso al descriptor (sd) devuelto por accept � El proceso ligero hijo creado podría usar sd en tratar_petición mientras que un

nuevo sd es asignado en accept

� Condiciones 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.

� Necesario sincronizar las acciones con mutex y variables condicionales� En el proceso servidor principal

� En los procesos ligeros hijos

116

Necesario sincronización

� El proceso ligero principal debe ejecutar:

for (;;) {sd = accept(s, (struct sockaddr *) &cliente, &len);pthread_create(&thid, &attr, tratar_peticion, &sd);/* esperar a que el hijo copie el descriptor */

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.

117

pthread_mutex_lock(&m);while(busy == TRUE)

pthread_cond_wait(&m, &c);busy = TRUE;pthread_mutex_unlock(&m);

}

Necesario sincronización

� El proceso ligero hijo debe ejecutar:

void tratar_peticion (int * s) {

int s_local;

pthread_mutex_lock(&m);

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.

s_local = *s;

busy = FALSE;

pthread_cond_signal(&c);

pthread_mutex_unlock(&m);

/* tratar la petición utilizando el descriptor s_lo cal */

pthread_exit(NULL);

}

118

Servidor concurrente en Java (streams)

while (true){

try {

Socket cliente = serverAddr. accept();

new TratarPeticion (cliente).start();

}

catch(Exception e) {

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.

System.err.println("excepcion " + e.toString() );

e.printStackTrace() ;

}

}

}

}

119

Servidor concurrente en Java (streams)class TratarPeticion extend Thread {

private Socket sc;

TratarPeticion (Socket s) {

sc = s;

}

public void run() {

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.

public void run() {

// TODO: código del cliente

}

120

Bibliografía y ejemplos

� Ejemplos de programas usando sockets:

� Ejemplo de sockets

� Ejemplo de uso de sockets en Java

� http://www.php-es.com/ref.sockets.html

� Sockets en Java

Programas de ejemplos de sockets y RPC

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.

� Programas de ejemplos de sockets y RPC

121