Capítulo 22: Interfaz de Socket

18
1 Capítulo 22: Interfaz de Socket ICD 327: Redes de Computadores Agustín J. González

description

Capítulo 22: Interfaz de Socket. ICD 327: Redes de Computadores Agustín J. González. Introducción. ¿Cómo las aplicaciones se comunican con la familia de protocolos de software y así logran comunicación con aplicaciones remotas? - PowerPoint PPT Presentation

Transcript of Capítulo 22: Interfaz de Socket

Page 1: Capítulo 22: Interfaz de Socket

1

Capítulo 22: Interfaz de Socket

ICD 327: Redes de Computadores

Agustín J. González

Page 2: Capítulo 22: Interfaz de Socket

2

Introducción• ¿Cómo las aplicaciones se comunican con la familia de

protocolos de software y así logran comunicación con aplicaciones remotas?

• La interfaz de programas de aplicación usada para inter-actuar con los protocolos de red se conocen como las APIs para la programación de red. La más conocida y difundida es la API de Socket (Socket Application Program Interface).

• A través de la interfaz de socket, las aplicaciones especifican los detalles de la comunicación como: qué protocolo se usará, es una aplicación cliente o servidor, y máquina remota.

• En el sistema operativo UNIX esta API es parte del SO. Otros sistemas operativos han creado una biblioteca (library) que implementa todos los llamados de la API de socket y así el código UNIX puede ser fácilmente compilado y ejecutado.

Page 3: Capítulo 22: Interfaz de Socket

3

Modelo de comunicación de Socket y I/O en UNIX

• El modelo empleado en socket para la comunicación entre aplicaciones remotas es similar al usado en la comunicación con cualquier dispositivo de I/O en UNIX. Enviar datos a una aplicación remota usa el mismo tipo de llamados que enviar datos a un archivo.

• El modelo se conoce con el nombre de paradigma open-read-write-close (abrir-leer-escribir-cerrar). El nombre refleja la secuencia típica para una la transferencia de información.

• En UNIX cuando se abre un archivo se retorna un descriptor de archivo. Cuando se abre un socket también se retorna un descriptor.

• Un descriptor es un entero. El SO usa este entero para entrar en una tabla que contiene todos los atributos del dispositivo al cual se refiere el descriptor.

Page 4: Capítulo 22: Interfaz de Socket

4

Parámetros usados en la API de Sockets

• Las mayores diferencias entre la comunicación vía sockets y manejo de archivos es la la forma de abrir el canal.

• Para crear un sockets la aplicación debe especificar :– Protocolo de transporte (su familia y protocolo dentro de la

familia)

– Dirección de la máquina remota o dirección local donde se esperará por requerimientos remotos,

– Es una cliente o un servidor,

– El puerto asociado a la aplicación

Page 5: Capítulo 22: Interfaz de Socket

5

Creación y cierre de un socket

• Creación:int descriptor;descriptor = socket(protocolFamily, type, protocol);donde:– Familia de protocolo: PF_INET, PF_APPLETALK

– Tipo: SOCK_STREAM para servicios de conexión y SOCK_DGRAM para servicios sin conexión.

– Protocolo: El protocolo particular a ser usado de la familia de protocolo. En TCP/IP, éste puede ser tcp o udp.

• Cierre del un socket:close(descriptor);Se termina la conexión antes de cerrar el socket.

Page 6: Capítulo 22: Interfaz de Socket

6

Procedimientos en servidor• Procedimiento bind

Este procedimiento asocia o liga un socket con una dirección IP y un puerto local.bind(descriptor, local_addr, addr_len);– Descriptor: es el descriptor del socket.

– Dirección local: es una estructuraconteniendo IP local y puerto local.

– Largo de dirección: entero que especifica el largo de la estructura local_addr.

• Como el llamado debe servir para varios protocolos, la estructura en genérica:

Page 7: Capítulo 22: Interfaz de Socket

7

Procedimientos en servidor (cont..)• struct sockaddr {

u_char sa_len; // largo totalu_char sa_family; // familia de la direcciónchar sa_data[14]; //la dirección

}

• En el caso particular de TCP/IP el campo dirección está especificado como sigue:

• struct sockaddr_in {u_char sin_len; // largo totalu_char sin_family; // familia de la direcciónu_short sin_port; // número de puertostruct in_addr sin_addr; // dirección IPchar sin_zero[8]; // no usados

}

Page 8: Capítulo 22: Interfaz de Socket

8

Procedimientos en servidor (cont..)• Procedimiento listen

listen( descriptor, queue_size);Instruye al OS que el socket es pasivo y desea tener a lo más queu_size requerimientos de conexión pendientes.

• El sistema rechaza requerimientos cuando la cola se llena.

• Procedimiento acceptnewDescriptor = accept(descriptor, c_address, c_address_len);

• Esta llamada es usada por servidores que usan servicios de conexión.

• c_address es del tipo struct sockaddr ya visto.

• Luego de aceptar una conexión, el servidor atiende al ciente a través del descriptor especialmente creado para él. Mientras tanto el servidor puede aceptar nuevas conexiones en el descriptor original.

Page 9: Capítulo 22: Interfaz de Socket

9

Procedimientos en cliente• Procedimiento connect

connect(descriptor, srv_address, srv_address_len);

srv_address: es una estructura del tipo struct sockaddr que contiene la dirección del servidor.srv_address_len es el largo de la estructura.

• Cuando el servicio es de conexión, connect establece la conexión con el servidor, el cual debe aceptar con accept().

• Cuando el servicio es sin conexión, connect registra los datos del servidor al cual se le enviarán los datagramas posteriormente. Así no es necesario especificar el destinatario en cada datagrama.

Page 10: Capítulo 22: Interfaz de Socket

10

Procedimientos de envío y recibo• Procedimiento send

int send (descriptor, data, length, flags);

data es la dirección de memoria donde se encuentran los datos a enviar.Length: es el largo en bytes de la zona de datos. Ésta función retorna el número de bytes efectivamente enviados Flags: especifican opciones. Las aplicaciones normales no las usan. Son usadas por programas de monitoreo y debug.

• Procedimiento sendtoint sendto (descriptor, data, length, flags, dest_address, address_len);

Page 11: Capítulo 22: Interfaz de Socket

11

Procedimientos de envío y recibo• Procedimiento recv

int recv (descriptor, buffer, length, flags);

buffer es la dirección de memoria donde se deben depositar los datos a recibir.length: es el largo en bytes de los datos que se desean leer. Recv retorna el número de bytes efectivamente leídos.Flags: especifican opciones. Las aplicaciones normales no las usan. Son usadas por programas de monitoreo y debug.

• Procedimiento recvfromint recvfrom (descriptor, buffer, length, flags, source_address, address_len);

Page 12: Capítulo 22: Interfaz de Socket

12

Procedimientos de envío y recibo (cont..)

• Procedimientos read y writeint read (descriptor, buffer, length);int write( descriptor, data, length);

• Estos dos llamados son similares a send y recv, y se pueden usar indistintamente en servicios de conexión.

• Estos procedimientos no funcionan en servicios sin conexión.

• La gran ventaja de estos procedimientos es su generalidad. Las aplicaciones pueden transferir datos sin saber si se trata de un descriptor de archivo o un socket.

Page 13: Capítulo 22: Interfaz de Socket

13

Ejemplo: Servidor UDP#define PORTNUMBER 12345

int main(void)

{

char buf[1024];

int s, n, len;

struct sockaddr_in name;

s = socket(PF_INET, SOCK_DGRAM, 0); /* Create the socket. */

name.sin_family = AF_INET; /* Create the address of the server. */

name.sin_port = htons(PORTNUMBER);

name.sin_addr.s_addr = htonl(INADDR_ANY); /* Use the wildcard address.*/

len = sizeof(struct sockaddr_in);

bind(s, (struct sockaddr *) &name, len); /* Bind the socket to the address. */

while ((n = recv(s, buf, sizeof(buf), 0)) > 0) /* Read from the socket until end-of-file */

write(stdout, buf, n); /* and print what we get on the standard output. */

close(s);

}

Page 14: Capítulo 22: Interfaz de Socket

14

Ejemplo: Cliente UDP#define PORTNUMBER 12345

int main(void)

{

int n, s, len;

char buf[1024];

char hostname[64];

struct hostent *hp;

struct sockaddr_in name;

gethostname(hostname, sizeof(hostname)); /* Get our local host name. */

hp = gethostbyname(hostname); /* Look up our host's network address. */

s = socket(PF_INET, SOCK_DGRAM, 0); /* Create a socket in the INET domain. */

name.sin_family = AF_INET; /* Create the address of the server. */

name.sin_port = htons(PORTNUMBER);

memcpy(&name.sin_addr, hp->h_addr_list[0], hp->h_length); /* set IP address */

len = sizeof(struct sockaddr_in);

while ((n = read(0, buf, sizeof(buf))) > 0) /* Read from standard input, and */

sendto(s, buf, n, 0, (struct sockaddr*) &name, len); /* copy the data to the socket. */

sendto(s, buf, 0, 0, (struct sockaddr*) &name, len);

close(s);

}

Page 15: Capítulo 22: Interfaz de Socket

15

Otras funciones relacionadas

• Procedimientos getpeername: permite obtener la dirección y puerta remota a partir de un socket ya “conectado”.

• Procedimiento gethostname: permite obtener el nombre de la máquina local.

• Procedimientos getsockopt y setsockopt: permiten obtener y modificar atributos de un socket; por ejemplo, el tramaño del buffer usado por TCP para recibir paquetes.

• Procedimientos gethostbyname y gethostbyaddr: permiten obtener la información sobre una máquina a partir de su nombre o dirección IP.

Page 16: Capítulo 22: Interfaz de Socket

16

Cliente/Servidor TCP: Secuencia de Eventos

Send/recv

Send/recv

Page 17: Capítulo 22: Interfaz de Socket

17

Ejemplo: Servidor TCP#define PORTNUMBER 12345

int main(void)

{

char buf[1024];

int s, n ,ns, len;

struct sockaddr_in name;

s = socket(PF_INET, SOCK_STREAM, 0); /* Create the socket. */

name.sin_family = AF_INET; /* Create the address of the server. */

name.sin_port = htons(PORTNUMBER);

name.sin_addr.s_addr = htonl(INADDR_ANY); /* Use the wildcard address.*/

len = sizeof(struct sockaddr_in);

bind(s, (struct sockaddr *) &name, len); /* Bind the socket to the address. */

listen(s, 5); /* Listen for connections. */

ns = accept s,(struct scoket *) &name, &len); /* Accept a connection */

while ((n = recv(ns, buf, sizeof(buf), 0)) > 0) /* Read from the socket until end-of-file */

write(stdout, buf, n); /* and print what we get on the standard output. */

close(ns);

close(s);

}

Page 18: Capítulo 22: Interfaz de Socket

18

Ejemplo: Cliente TCP#define PORTNUMBER 12345

int main(void)

{

int n, s, len;

char buf[1024];

char hostname[64];

struct hostent *hp;

struct sockaddr_in name;

gethostname(hostname, sizeof(hostname)); /* Get our local host name. */

hp = gethostbyname(hostname); /* Look up our host's network address. */

s = socket(PF_INET, SOCK_STREAM, 0); /* Create a socket in the INET domain. */

name.sin_family = AF_INET; /* Create the address of the server. */

name.sin_port = htons(PORTNUMBER);

memcpy(&name.sin_addr, hp->h_addr_list[0], hp->h_length); /* set IP address */

len = sizeof(struct sockaddr_in);

connect(s, (struct sockaddr *) &name, len); /* Connect to the server */

while ((n = read(stdin, buf, sizeof(buf))) > 0) /* Read from standard input, and */

send(s, buf, n, 0); /* copy the data to the socket. */

/* OUT sendto(s, buf, 0, 0, (struct sockaddr*) &name, len); */

close(s);

}