Post on 27-Apr-2022
Práctica 1Programación de Aplicaciones
Distribuidas: Sockets UDP
Laboratorio de Comunicación de DatosITT Telemática – Septiembre 2011
Aplicaciones Distribuidas Su funcionalidad se distribuye en diferentes máquinas Servidor Web Aplicación FTP eMule…
Modelo cliente-servidor: Proceso cliente: envía peticiones Proceso servidor: atiende peticiones
Necesario canal de comunicación
Introducción
2
Aplicaciones Distribuidas Canal de comunicación entre dos máquinas UNIX
Introducción
Aplicacióncliente
TCP UDP
IP
Ethernet
Aplicaciónservidor
TCP UDP
IP
EthernetDirección
MAC(48 bits)
DirecciónIP
(32 bits)
PuertoTCP/UDP(16 bits)
ARP
3
Asociaciones y sockets Canal de comunicación
Protocolo, dirección local, proceso local, dirección remota, proceso remoto
Como un cable que une dos procesos Socket: extremo de un canal (enchufe)
Máquina local: protocolo, dirección local, proceso local Máquina remota: protocolo, dirección remota, proceso remoto
API de sockets Proporciona estructuras de datos y funciones para la programación de
aplicaciones distribuidas
Introducción
4
Establecimiento del canal: socket() Crea una canal de comunicaciones bidireccional
#include <sys/types.h>#include <sys/socket.h>int socket (int familia, int tipo, int protocolo)
Parámetros Familia: AF_INET Tipo:
Orientado a conexión (SOCK_STREAM), No orientado a conexión (SOCK_DGRAM)
Protocolo: 0 Devuelve identificador del socket (entero no negativo), -1 si
error. No asocia dirección IP ni puerto
Programación Sockets
5
Establecimiento del canal: bind() Asigna al socket una dirección IP y un puerto (TCP/UDP) locales
determinados.#include <sys/types.h>#include <sys/socket.h>int bind (int sockfd,
(struct sockaddr *) direccion, int longitud)
Parámetros sockfd: identificador socket devuelto por la función socket() direccion: estructura que contiene el puerto y la dirección IP locales longitud = sizeof (direccion)
Devuelve -1 en caso de error
Programación Sockets
6
Establecimiento del canal: bind() Estructura sockaddr_in (para IPv4)
#struct sockaddr_in {shortsin_family; /* AF_INET */u_short sin_port; /* puerto TCP/UDP */struct in_addr sin_addr; /* dirección IP */char sin_zero[8]; /* 8 bytes ceros */
}struct in_addr {u_long s_addr; /* dirección IP */
}
Programación Sockets
7
Establecimiento del canal: bind() Estructura sockaddr genérica
#struct sockaddr {short sa_family; /* AF_xxx */char sa_data[14]; /* 14 bytes familia */
}
Uso de la estructura La estructura sockaddr siempre se pasa por referencia
(dirección) Siempre va acompañada de su tamaño
Sentido aplicaciónkernel: paso por valor Sentido kernel aplicación: paso por referencia
Programación Sockets
8
Establecimiento del canal: bind()
Programación Sockets
Uso de bind() Obligatorio en el proceso servidor:
Informa al sistema operativo de que todo el tráfico recibido en un determinado puerto le corresponde
Opcional en el proceso cliente Si no se especifica puerto (sin_port=0) el SO asigna el
primero libre Si no se especifica dirección IP
(sin_addr=INADDR_ANY) se aceptan conexiones/datagramas por cualquier interfaz local
9
Establecimiento del canal: Ejemplo
Programación Sockets
if ((ds = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {error("socket");exit(1);
}
bzero ((char *) &servidor, sizeof (servidor);servidor.sin_family = AF_INET; /* familia Internet */servidor.sin_port = htons (5001); /* Puerto formato red */servidor.sin_addr.s_addr = inet_addr(“172.29.20.43”);
longitud1 = sizeof(servidor);
if( bind (ds, (struct sockaddr *) &servidor, longitud1) == -1 {error("bind");exit(1);
}
Creación del Socket UDP
Asocia el socket a una dirección IP y puerto
10
Funciones auxiliares
Programación Sockets
Inicializar a cero una estructura (e.g. sockaddr_in) bzero (char * direccion, int long)
Traducir direcciónes IP formato ASCII (xx.xx.xx.xx) a formato de red (y viceversa) unsigned long inet_addr (char * dir_ascii) char * inet_ntoa (struct in_addr dir_red)
Ordenación de bytes unsigned long htonl (x) /* h->n long */ unsigned short htons (x) /*h->n short */ unsigned long ntohl (x) /* n->h long */ unsigned short ntohs (x) /* n->hshort */
11
Envío de datagramas UDP: sendto()
Programación Sockets
Envía datos a través de un socket a un determinado destino#include <sys/types.h>#include <sys/socket.h>int sendto (int sockemisor, char * mensg,
int lgmensg, int opcion, (struct sockaddr *) destino, int lgdest);
Parámetros
Devuelve n° de bytes transmitidos, -1 en caso de error
sockemisor: descriptor socket origenmensg: datos del datagramalgmensg: longitud (n° bytes) datoslgdest = sizeof (destino)
opcion: 0destino: estructura sockaddr_in que contiene el puerto y la dirección IP
12
Recepción de datagramas: recvfrom()
Programación Sockets
Espera y lee un datagrama de la cola de recepción asociada a un socket#include <sys/types.h>#include <sys/socket.h>int recvfrom (int sockreceptor, char * mensg,
int lgmensg, int opcion, (struct sockaddr *) origen, int *lgorig);
Parámetros
Devuelve n° de bytes recibidos, -1 en caso de error
sockemisor: descriptor socket destinomensg: buffer recepciónlgmensg: longitud (n° bytes) bufferlgorig = sizeof (destino)
opcion: 0origen: estructura sockaddr_in que almacenará el puerto y la dirección IP del emisor
13
Cierre del canal: close()
Programación Sockets
Cierra el canal de comunicaciones bidireccional creado previamente por socket#include <sys/types.h>
#include <sys/socket.h>
close (int sockfd);
Parámetros sockfd: descriptor devuelto por socket()
14
Arquitectura básica del servidor UDP socket(): crea el canal
bind(): asocia al canal una dirección IP y un puerto
recvfrom(): recibe datos de un cliente
sendto(): envía datos al cliente a través del socket
Práctica I
15
Arquitectura básica del cliente UDP socket(): crea el canal
bind(): asocia al canal una dirección IP y un puerto
sendto(): envía datos al servidor a través del socket
recvfrom(): recibe datos del servidor
close(): cierra el canal
Práctica I
16
Ejemplo: Servidor de “eco” UDP/* * Ejemplo servidor datagrama eco (ecodgramserv.c)*/
#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>
#define SERVPUERTO 9999 /* puerto de escucha del servidor */#define MAXBUFF 100 /* longitud máxima mensajes replicar con
ECO */
Práctica I
17
Ejemplo: Servidor de “eco” UDPmain(){
int ds; /* descriptor socket */struct sockaddr_in servidor; /* info. Servidor */struct sockaddr_in cliente; /* info. Cliente */int longitud1, longitud2, n, m;char buff[MAXBUFF]; /* buffer recepción mensajes*/
if ((ds = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {error("socket");exit(1);
}
Práctica I
Creación del Socket UDP
18
Ejemplo: Servidor de “eco” UDP
bzero ((char *) &servidor, sizeof (servidor);servidor.sin_family = AF_INET; /* familia */servidor.sin_port = htons (PUERTO); /*formato red */servidor.sin_addr.s_addr = INADDR_ANY; /* Cualquier IP */
longitud1 = sizeof(servidor);
if( bind(ds,(struct sockaddr *)&servidor, longitud1) == -1 {
error("bind");exit(1);
}
Práctica I
Inicializar sockaddr_in
Enlazar la dirección local al socket
19
Ejemplo: Servidor de “eco” UDPfor (;;) {
longitud2 = sizeof (cliente);bzero ((char *) &cliente, longitud2);
n = recvfrom(ds, buff, MAXBUFF, 0, (struct sockaddr *)&cliente, &longitud2);
if (n == -1) {error ("recvfrom");exit (1);
}
printf (“Datagrama procedente de %s\n",inet_ntoa (cliente.sin_addr));
printf (“Butes recibidos: %d\n",n);printf(“Contenido datagrama: %s\n",buff);
Práctica I
Recibir datagrama
20
Ejemplo: Servidor de “eco” UDPm = sendto (ds, buff, n, 0,
(struct sockaddr *)&cliente, &longitud2);if (m == -1) {
error (“sendto");exit (1);
}}
close (ds);}void error (char * mensaje){
perror (mensaje);exit(1);
}
Práctica I
Enviar datagrama
Cerrar socket
21
Bibliografía
J. M. Arco Rodriguez et al. Programación de Aplicaciones en Redes de Comunicaciones bajo Entorno Unix
Páginas man de Linux
Referencias
22