Capítulo 22: Interfaz de Socket
-
Upload
ocean-santos -
Category
Documents
-
view
27 -
download
0
description
Transcript of Capítulo 22: Interfaz de Socket
![Page 1: Capítulo 22: Interfaz de Socket](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/1.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/2.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/3.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/4.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/5.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/6.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/7.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/8.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/9.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/10.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/11.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/12.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/13.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/14.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/15.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/16.jpg)
16
Cliente/Servidor TCP: Secuencia de Eventos
Send/recv
Send/recv
![Page 17: Capítulo 22: Interfaz de Socket](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/17.jpg)
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](https://reader036.fdocuments.ec/reader036/viewer/2022071808/56813594550346895d9d05ce/html5/thumbnails/18.jpg)
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);
}