Tema 2: Interfaz socket

Anuncio
Bloque 2: Aplicaciones extremo a extremo
Tema 2: Interfaz socket
PROTOCOLOS DE COMUNICACIONES
Área de Ingeniería Telemática
Profesora: María Canales
Curso 2009-10
Departamento de Ingeniería Electrónica y Comunicaciones
Universidad de Zaragoza
Contenidos
z
Interacción con el nivel de transporte:
–
z
interfaz socket (concepto y aplicación)
Clases prácticas:
–
–
estudio de ejemplos (afianzando teoría)
programación
Tema 2: Interfaz socket
2
Introducción
z
Función del nivel de red:
–
z
Función del nivel de transporte:
–
z
comunicación entre hosts
comunicación entre procesos
Interfaz con el nivel de transporte:
–
Iremos viendo en
detalle a lo largo de la
asignatura…
host
Sistema operativo, sockets
host
Tema 2: Interfaz socket
3
Interfaz socket
z
Interfaz con el nivel de transporte proporcionado por el
sistema operativo
–
Los procesos pueden pedir un socket
z
z
–
–
para usar transporte UDP
para usar transporte TCP
Se identifican por un descriptor de ficheros
Un proceso puede pedir varios sockets
Aplicaciones
de Usuario
Aplicación
de usuario
FTP
WWW
Interfaz Socket
Sistema
Operativo
Tema 2: Interfaz socket
TCP/IP
Netbios
IPX/SPX
Driver
Hardware de red
4
Interfaz socket
Tema 2: Interfaz socket
5
Interfaz socket
z
El API de sockets
–
API: Application Program Interface
z
z
z
Un conjunto de funciones, protocolos y herramientas
para ayudar al programador de aplicaciones a utilizar
un determinado recurso, en nuestro caso la red
Origen: del UNIX de Berkeley BSD 4.2
Hay otros APIs para usar la red
XTI/TLI de System V
– RPCs (remote procedure calls)
–
z
Pero hoy en día sockets es el más usado
–
De hecho es el estándar en Linux, MacOSX y Windows (al
menos hasta el .net)
Tema 2: Interfaz socket
6
Interfaz socket – tipos de sockets
z
Stream (SOCK_STREAM)
–
–
–
–
z
Orientado a conexión: información de estado
Si PF_INET se corresponde con el protocolo TCP
Comportamiento de cliente o servidor
No mantiene separación entre mensajes
Comunicación uno-a-uno
Datagrama (SOCK_DGRAM):
–
–
–
Orientado a datagramas: no información de estado
Si PF_INET se corresponde con el protocolo UDP
Un socket ligado a un puerto
z
z
–
z
Streams: flujos de
octetos que incorporan
control de error y de flujo
puede mandar a cualquier otro socket UDP
puede recibir de cualquier otro socket UDP
Mantiene separación entre mensajes
Datagramas: bloques de
datos de usuario de hasta
64 KB, sin control de
error o de flujo
Permiten difusiones
Raw (SOCK_RAW)
–
Permite el acceso a los protocolos internos como IP.
Tema 2: Interfaz socket
7
Interfaz socket - direcciones
z
z
z
Cada socket debe tener asignada una dirección única.
Dependientes del dominio.
Las direcciones se usan para:
–
–
z
Se utiliza la estructura genérica de dirección:
–
z
Asignar una dirección local a un socket (bind).
Especificar una dirección remota (connect o sendto).
struct sockaddr mi_dir;
Cada dominio usa una estructura específica.
–
–
–
Uso de cast en las llamadas.
Direcciones en PF_INET (struct sockaddr_in).
Direcciones en PF_UNIX (struct sockaddr_un).
Formato genérico de dirección
0
16
Address Family
31
Address octets 0-1
Address octets 2-5
Address octets 6-9
Address octets 10-13
Tema 2: Interfaz socket
8
Interfaz socket - direcciones
z
Direcciones en PF_INET
–
Dirección =
z
–
Estructura struct sockaddr_in
z
z
DIRECCIÓN host (32 bits) + PUERTO servicio (16 bits)
debe iniciarse a 0 (bzero).
Una transmisión está caracterizada por cinco parámetros
únicos:
–
(@IPsrc, PORTsrc, @IPdst, PORTdst, PROTO -TCP/UDP)
Formato de dirección TCP/IP (PF_INET)
0
16
Address Family (AF_INET)
31
Protocol port
IP address
Tema 2: Interfaz socket
9
Interfaz socket - direcciones
z
Usuarios manejan direcciones en forma de texto:
–
–
z
decimal-punto: 138.100.8.100
dominio-punto: laurel.datsi.fi.upm.es
Conversión a binario desde decimal-punto:
int inet_aton(char *str, struct in_addr *dir)
z
z
z
str: contiene la cadena a convertir.
dir: resultado de la conversión en formato de red.
Conversión a binario desde dominio-punto:
struct hostent *gethostbyname(char *str)
z
z
str: cadena a convertir.
Devuelve la estructura que describe al host.
Tema 2: Interfaz socket
10
Interfaz socket - datos
z
Orden de los bits
–
Host Byte Order: los equipos difieren en su forma de almacenar
la información (bytes):
z
z
–
Little endian (“little end comes first”): el bit menos significativo
almacenado en la dirección de memoria menor: byte0, byte1, byte2,…
Big endian (“big end comes first”): el bit más significativo
almacenado en la dirección de memoria menor: byte3, byte2, byte1,..
Network Byte Order: TCP/IP es big endian
z
Escribir código portable requiere conversión de tipos:
htons() y htonl() para convertir a network byte order
– ntohs() y ntohl() para convertir a host order
–
z
Usar cuando sea necesario enviar/recibir estructuras de datos más
grandes que un byte
Arquitectura
little-endian
Dato a enviar: 5
3 2
1
0
0005
Valor: 0x224+0x216+0x28+5
Tema 2: Interfaz socket
0005
Arquitectura
big-endian
0
1
2
3
0005
Valor: 5x224+0x216+0x28+0
Dato a recibido: 83.886.080
11
Interfaz socket – Funciones básicas
socket()
CREA un nuevo socket y devuelve su descriptor
bind()
ASOCIA un socket a una DIRECCIÓN (@IP+port)
listen()
ESTABLECE la COLA de peticiones de conexión (SERVIDOR)
accept()
ACEPTA una petición de conexión (SERVIDOR)
connect()
INICIA una conexión con un host remoto (CLIENTE)
recv()
RECIBE datos de un descriptor de socket (asociado a una dirección) – TCP (UDP si antes connect)
write()
ENVIA datos a un descriptor de socket (asociado a una dirección) – TCP
read()
RECIBE datos de un descriptor de socket (asociado a una dirección) – TCP
send()
ENVIA datos a un descriptor de socket (asociado a una dirección) – TCP (UDP si antes connect)
recvfrom()
RECIBE datos de un descriptor de socket DE UN DESTINO ESPECIFICADO (@IP+port) – UDP
sendto()
ENVIA datos a un descriptor de socket A UN DESTINO ESPECIFICADO (@IP+port) – UDP
close()
CIERRE de un descriptor de socket (en un sentido)
gethostbyname()
Dado un nombre de host, devuelve una estructura que especifica su nombre DNS y
su dirección IP
getservbyname()
Dado un nombre de servicio y protocolo, devuelve una estructura que especifica su
nombre y su dirección (puerto)
gethostname()
Devuelve el nombre de host de un host local
ntohs()/ntohl()
Convierte short/long de network byte order (big endian) a host byte order
htons()/htonl()
Convierte short/long de host byte order a network byte order
inet_ntoa() /inet_addr()
Convierte una dirección IP de 32 bits (network byte order) en un string de notación
decimal (con puntos)
Tema 2: Interfaz socket
12
Interfaz socket – socket TCP
z
Modo cliente
–
–
–
–
–
z
Toma la iniciativa de establecer la comunicación
Conoce la dirección y el puerto del servidor
Abre un socket y lo usa para conectarse a un servidor
A partir de ahí intercambia datos con el servidor
Normalmente el cliente pide cosas que le envía el servidor
Modo servidor
–
–
–
–
–
–
Espera recibir comunicaciones de clientes
Elige un puerto que deberá ser “conocido” por los clientes
Abre un socket y espera recibir conexiones
Obtiene un nuevo socket para hablar con cada cliente
A partir de ahí intercambia datos con el cliente
Normalmente el servidor recibe peticiones y las contesta
Tema 2: Interfaz socket
13
Interfaz socket – socket TCP
Proceso servidor
socket()
bind()
Proceso cliente
listen()
socket()
Abrir conexión
connect()
accept()
Posible
Ejecución
en Paralelo
Petición
recv()/read()
send()/write()
Respuesta
recv()/read()
close()
Tema 2: Interfaz socket
send()/write()
close()
close()
14
Interfaz socket – socket TCP
z
Creación de un socket
int = socket (int pf, int type, int protocolo)
–
pf: especifica la familia de protocolos a utilizar con este socket,
ayudando así a interpretar la dirección de red. Se incluyen las
familias:
z
–
PF_INET: familia TCP/IP.
type: especifica el tipo de comunicación que se desea:
z
z
z
SOCK_STREAM: servicio fiable.
SOCK_DGRAM: servicio sin conexión.
SOCK_RAW: permite el acceso a protocolos de bajo nivel.
–
protocolo: permite seleccionar un protocolo específico. Si es
cero se toma el protocolo por defecto.
–
devuelve: un descriptor que identifica al socket abierto.
–
El socket creado no tiene dirección asignada
Tema 2: Interfaz socket
15
Interfaz socket – socket TCP
z
Enlace de un socket a una dirección local
int bind(int socket, struct sockaddr* localaddr, int addrlen)
–
Inicialmente, un socket se crea sin ninguna asociación a direcciones locales
o destino. En caso de TCP/IP, los procesos servidores han de especificar al
sistema el puerto con el que operan.
–
socket: especifica al descriptor del socket abierto.
localaddr: es una estructura que especifica la dirección local a la que el
socket va a ser enlazado (depende de la familia de protocolos)
–
z
La estructura de la dirección se denomina sockaddr
–
sockaddr_in en caso de TCP/IP.
–
addrlen: es un entero que especifica la longitud de la dirección medida en
octetos (sizeof).
–
Si no se asigna dirección (típico en clientes) se le asigna automáticamente
(puerto efímero) en su primera utilización (connect o sendto)
Tema 2: Interfaz socket
16
Interfaz socket – socket TCP
z
Especificar número de conexiones
–
–
–
–
–
int listen(int socket, int qlength)
Para evitar el rechazo de peticiones de conexión a un servidor
debido a que éste está respondiendo a una solicitud anterior, el
servidor puede pedir al software del protocolo subyacente que
guarde esas peticiones en una cola de espera hasta que
tenga tiempo para procesarlas.
socket: especifica al descriptor del socket abierto.
qlength: especifica la longitud de la cola de espera.
Si llega una petición y la cola de peticiones está completa, el
sistema operativo rechaza la petición.
listen se aplica únicamente a sockets que utilizan un servicio de
entrega de datos fiable.
Tema 2: Interfaz socket
17
Interfaz socket – socket TCP
z
Aceptar conexiones
int accept(int socket, struct sockaddr *addr, int *addrlen)
–
Tras los pasos dados un socket se queda a la espera de
conexiones.
–
socket: especifica al descriptor del socket abierto.
addr: es puntero a una estructura de direcciones que albergará
la dirección del cliente (devolución tras la llamada)
addrlen: es un puntero a un entero que especificará la longitud
de la dirección del cliente (devolución tras la llamada).
–
–
–
devuelve: el descriptor del nuevo socket creado por el
servidor para atender la petición y que tiene su destino
conectado al cliente.
z
z
El socket original queda abierto a la espera de nuevas peticiones de
conexión.
El socket creado es a través del cual se realiza la conexión
cliente/servidor
Tema 2: Interfaz socket
18
Interfaz socket – socket TCP
z
Aceptar conexiones
–
Gestión de peticiones:
z
Concurrente: se pueden servir varias peticiones
simultáneamente
–
Opciones:
z Varios hilos (threads)
z Varios procesos (process)
z Un único hilo/proceso que gestiona varias conexiones
(select)
Veremos ejemplo…
z
Iterativa: se sirve una petición tras otra
–
–
sirve la petición.
Cuando termina cierra newsock y llama nuevamente a accept.
Tema 2: Interfaz socket
19
Interfaz socket – socket TCP
z
Conexión de sockets con direcciones destino
int connect(int socket, struct sockaddr* destaddr, int addrlen)
–
Inicialmente un socket no está asociado a ningún destino. Para
conectar un socket a un destino en modo permanente se debe
especificar la conexión.
socket: especifica al descriptor del socket abierto.
destaddr: especifica mediante una estructura de direcciones del
tipo sockaddr_in, la dirección destino.
addrlen: especifica la longitud de la dirección destino.
–
Servicio sin conexión (SOCK_DGRAM)
–
–
–
z
–
esta función lo único que hace es almacenar localmente la dirección
destino. De esta manera, se posibilita la transferencia de datos sin
especificar cada vez la dirección destino.
Servicio con conexión TCP (PF_INET y SOCK_STREAM)
z
connect construye una conexión TCP con el destino y retorna un error
caso de no poder.
Tema 2: Interfaz socket
20
Interfaz socket – socket TCP
z
Envío de datos:
–
–
Puede usarse la llamada write sobre el descriptor de socket (como un
fichero)
O la llamada específica:
int send(int socket, char *buffer, int length, int flags)
–
z
Devuelve el nº de bytes enviados.
Recepción de datos :
–
–
Puede usarse la llamada read sobre el descriptor de socket.
O la llamada específica:
int recv(int socket, char *buffer, int length, int flags)
–
z
Devuelve el nº de bytes recibidos.
Los flags implican aspectos avanzados como enviar o recibir datos
urgentes (out-of-band).
Tema 2: Interfaz socket
21
Interfaz socket – socket TCP
z
Finalización
close(int socket)
–
socket: especifica al descriptor del socket abierto.
–
Disminuye la cuenta de referencia para un socket y lo destruye si
la cuenta llega a cero.
Cuando un programa termina de una manera inesperada, es el
sistema el que cierra todos los sockets que ese programa había
abierto.
–
int shutdown(int socket, int how)
–
–
socket: especifica al descriptor del socket abierto.
how: especifica el tipo de cierre
z
z
z
–
0: Dejar de recibir
1: Dejar de transmitir
2: Dejar de recibir y transmitir
Es más insistente que close porque también deshabilita cualquier
descriptor en cualquier copia (fork) en otros procesos
Tema 2: Interfaz socket
22
Interfaz socket – socket TCP
z
Concurrencia (ejemplo)
–
Mediante múltiples procesos: herencia de un
socket
z
UNIX, para comenzar nuevos programas de aplicación,
utiliza las funciones
fork: crea copia separada del programa de aplicación
z La copia hereda el acceso a todos los sockets
abiertos
– exec: el programa comenzado reemplaza al que lo
llamó.
z La nueva aplicación retiene el acceso a los sockets
abiertos
–
Tema 2: Interfaz socket
23
Interfaz socket – socket TCP
z
Atención a múltiples peticiones
–
Servidor Iterativo: Atención por turno.
int socket, socket_cliente;
struct sockaddr_in direccion;
int direccionlen;
while (1)
{
Cast en las funciones (direccion es
tipo sockaddr_in, y hay que pasar
un parámetro tipo sockaddr)
direccionlen = sizeof(direccion);
socket_cliente = accept( socket , (struct sockaddr *)&direccion ,
&direccionlen );
/* aquí podríamos decidir si aceptamos al cliente según de
donde venga comprobando su dirección de origen que
devuelve accept */
}
atender_al_cliente( socket_cliente );
close( socket_cliente );
Tema 2: Interfaz socket
24
Interfaz socket – socket TCP
z
Atención a múltiples peticiones
–
Servidor Concurrente: Otro proceso/hilo
int socket, socket_cliente;
struct sockaddr_in direccion;
int direccionlen;
int pid;
while (1)
{
direccionlen = sizeof(direccion);
socket_cliente = accept( socket , (struct sockaddr *)&direccion ,
&direccionlen );
pid = fork();
proceso hijo!
if ( pid == 0 )
{
atender_al_cliente( socket_cliente );
close( socket_cliente );
exit(0);
}
}
close( socket_cliente );
Tema 2: Interfaz socket
25
Interfaz socket – socket TCP
z
Atención a múltiples peticiones
–
Servidor Concurrente: asíncrono con select()
–
También podemos programar servidores concurrentes
utilizando un solo proceso
Función select() permite saber qué descriptor de fichero
(socket) tiene algo para leer
–
z
–
Para ello le indicamos un conjunto de descriptores en los que estamos
interesados
Manejo de conjuntos de descriptores
z
z
z
Tipos y macros definidos en #include <unistd.h>
Tipo fd_set representa un conjunto de descriptores de ficheros
Macros
–
–
–
–
FD_ZERO(&fdset); borra un conjunto de descriptores
FD_SET(fd, &fdset); añade fd al conjunto
FD_CLR(fd, &fdset); quita fd del conjunto
FD_ISSET(fd, &fdset); comprueba si fd esta en el conjunto
Tema 2: Interfaz socket
26
Interfaz socket – socket TCP
z
Atención a múltiples peticiones
–
Servidor Concurrente: asíncrono con select()
int = select(int n, fd_set *rfds, fd_set *wfds, fd_set*efds, struct timeval *timeout)
–
–
–
–
–
–
n: número máximo de descriptores en los conjuntos
rfds: puntero a conjunto de descriptores (sockets) ⇒ interés en
si tienen algo para leer
wfds: puntero a conjunto de descriptores (sockets) ⇒ interés en
si tienen algo para escribir
efds: puntero a conjunto de descriptores (sockets) ⇒ interés en
si tienen errores que informar
timeout: tiempo a esperar por novedades. Si pasa ese tiempo y
no hay novedades devuelve 0
devuelve: número de descriptores con novedades (0: no hay
novedades, -1: error)
Tema 2: Interfaz socket
27
Interfaz socket – socket TCP
z
Atención a múltiples peticiones
–
Servidor Concurrente: asíncrono con select()
–
Establecer socket como no bloqueante:
z
Ejemplo, recv/send (I/O):
int ioctl (int fd, long cmd, u_long *argp)
z
z
z
–
Con select() ya no es un problema hacer un servidor que lea de varios
sockets
z
z
z
–
sd = socket abierto
Cmnd = comando, ej FINBIO
Argp = valor (0 / nonzero ⇒ bloqueante / no bloqueante)
Mantenemos una lista de sockets que tenemos abiertos
preguntamos con select() cuales exigen contestación.
tener una conexión pendiente de aceptar es una novedad de lectura
El servidor es así monoproceso
z
z
Más complicado. Tiene que llevar el estado de todos los clientes a la vez
Pero es más fácil la comunicación si los procesos que atienden a varios clientes
deben comunicarse
Tema 2: Interfaz socket
28
Interfaz socket – socket UDP
z
Transporte UDP: servicio no orientado a Conexión.
–
–
No hace falta establecimiento
Preparación del socket más simple
z
z
El mismo socket se puede usar para recibir y enviar a
varios sockets remotos
–
z
Mismas funciones vistas hasta ahora, alguna no es
necesaria…
La sincronización de cuándo tengo que enviar o recibir
dependerá del protocolo de aplicación que construyamos
Aparte UDP se puede usar para otros usos
eminentemente no orientados a conexión:
–
–
Uno a varios
Multicast y broadcast
Tema 2: Interfaz socket
29
Interfaz socket – socket UDP
Proceso
socket()
bind()
Proceso
Proceso
socket()
socket()
bind()
bind()
sendto()
recvfrom()
close()
Petición
sendto()
recvfrom()
Respuesta
recvfrom()
sendto()
close()
close()
Tema 2: Interfaz socket
30
Interfaz socket – socket UDP
z
Servidores sin estado
–
–
–
–
No se establece una conexión (connect/accept) previa.
Para usar un socket para transferir basta con crear el socket y
reservar la dirección (bind).
El mismo socket para atender a varios clientes
Recibimos datagramas y enviamos respuestas
int socket;
struct sockaddr_in direccion;
void *buffer;
int direccionlen, buflen, recibidos;
while (1) {
}
direccionlen = sizeof(direccion);
recibidos = recvfrom(socket,buffer,buflen,0,
(struct sockaddr *)& direccion, &direccionlen);
aenviar = respuesta_al_cliente( buffer, recibidos, direccion );
/* la respuesta se construye en el buffer */
sendto(socket,buffer,aenviar,0,
(struct sockaddr *)&direccion, &direccionlen);
Tema 2: Interfaz socket
31
Interfaz socket – socket UDP
z
Envío y recepción de datos
int sendto(int socket, char *buffer, int length, int flags,
struct sockaddr *dir, int *addrlen)
Especificamos el destino de la conexión
int recvfrom(int socket, char *buffer, int length, int flags,
struct sockaddr *dir, int *addrlen)
Nos devuelve la dirección que ha enviado
Tema 2: Interfaz socket
32
Interfaz socket
z
Resumen de funciones de envío y recepción de datos:
–
Para enviar datos existen 5 posibles llamadas al sistema
operativo:
z
z
z
z
z
–
write(socket, buffer, length).
writev(socket, iovector, vectorlen).
send(socket, message, length, flags).
sendto(socket, message, length, flags, destaddr, addrlen).
sendmsg(messagestruct, flags).
Para recibir datos existen 5 posibles llamadas al sistema
operativo:
z
z
z
z
z
read(socket, buffer, length).
readv(socket, iovector, vectorlen).
recv(socket, message, length, flags).
recvfrom(socket, message, length, flags, fromaddr,addrlen)
recvmsg(messagestruct, flags).
Tema 2: Interfaz socket
33
Interfaz socket
z
Miscelanea:
–
Transformación de valores:
z
De formato host a red:
–
z
De formato de red a host:
–
–
z
z
gethostbyname(namestr).
gethostbyaddr(addr, len, type).
Obtención de información sobre redes (nombre, alias, dirección tipo entero
y dirección de 32 bits)
z
z
–
gethostname(name, length).
sethostname(name, length).
Obtención de información sobre host (nombre, dirección, etc.)
z
–
Enteros largos/cortos: ntohl() / ntohs()
Obtención y especificación de nombres de host.
z
–
Enteros largos/cortos: htonl() / htons()
getnetbyname(name).
getnetbyaddr(netaddr, addrtype).
Obtención de información sobre servicios de red (nombre, protocolo y
puerto)
z
z
getservtbyname(name, proto).
getservbyport(port, proto).
Tema 2: Interfaz socket
34
Interfaz socket – conceptos avanzados
z
Comunicación Síncrona y Asíncrona
–
Bloqueantes (síncronas):
z
z
z
–
No bloqueantes (asíncronas):
z
z
–
el emisor (send) se suspende hasta que el mensaje no es recibido.
Una llamada a receive no retorna hasta que el mensaje no ha sido
colocado en el buffer que especifica el receptor.
En algunos sistemas el receptor puede especificar de qué emisor
desea recibir, en cuyo caso permanecerá bloqueado hasta que lleguen
los mensajes que le interesan.
un send no bloqueante retorna el control al llamador inmediatamente
antes que el mensaje sea enviado.
Un receive no bloqueante le indica al kernel el buffer donde se dejará
el mensaje y la llamada retorna inmediatamente.
Evitar bloqueos:
z
z
Trabajar con múltiples procesos o hilos
Funcionamiento de sockets asíncronos (la llamada a la función vuelve,
y se “avisa” del evento cuando sucede)
Tema 2: Interfaz socket
35
Interfaz socket – conceptos avanzados
z
Primitivas de comunicación bloqueantes vs. no bloqueantes:
–
Bloqueante: no se vuelve tras una llamada a una función hasta
que termina la ejecución
z
Problema: en un S.O. multitarea, se pone otro proceso en ejecución,
en un S.O. que no lo permite, éste se bloquea
–
No bloqueante: se sale de la función aún sin haber acabado la
ejecución
–
Ejemplos:
z
z
z
z
z
–
Envío no bloqueante: El emisor continua al pasar el mensaje al núcleo.
Envío bloqueante: El emisor espera a que el núcleo transmita por red
el mensaje.
Envío bloqueante fiable: El emisor espera a que el núcleo receptor
recoge el mensaje.
Envío bloqueante explícito: Ídem al anterior, pero es la aplicación
receptora la que confirma la recepción.
Petición-Respuesta: El emisor espera a que el receptor procese la
operación para reanudar la ejecución.
Evitar bloqueos:
z
z
Trabajar con múltiples procesos o hilos
Funcionamiento de sockets asíncronos (select)
Tema 2: Interfaz socket
36
Interfaz socket – conceptos avanzados
z
Usando el DNS
struct hostent *gethostbyname(const char *name)
–
–
name: nombre por el que se pregunta resolver la asociación con
dirección IP
resultado: es una estructura struct hostent
z
Contiene todos las IPs asociadas a ese nombre
struct hostent
{
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
};
#define h_addr h_addr_list[0] /* address, for backward compatibility */
Tema 2: Interfaz socket
37
Interfaz socket – conceptos avanzados
z
Controlar opciones de los sockets
int setsockopt(int s, int level, int optname,
const char *optval, socklent_toptlen)
–
–
s: socket a controlar
Qué quiero cambiar en el socket:
z
z
–
Valor que quiero dar a la opción:
z
z
–
z
level: nivel de la opción
optname: nombre de la opción
optval: valor de la opción (como diferentes opciones pueden requerir
diferentes tipos de valor se pasa como un puntero y un tamaño
optlen: longitud del valor de la opción
Devuelve código de error
Para leer los valores..
int getsockopt(int s, int level, int optname,
const char *optval, socklent_toptlen)
Tema 2: Interfaz socket
38
Interfaz socket – conceptos avanzados
z
Controlar opciones de los sockets
–
Permiten cambiar el comportamiento de los niveles de protocolos
inferiores usados por el socket
–
Algunos ejemplos:
Nivel
Opción
Efecto
SOL_SOCKETS
SO_SNDBUF
Elige el tamaño del buffer de envío del nivel de
transporte del socket
SO_RCVBUF
Elige el tamaño del buffer de recepción del nivel de
transporte del socket
SO_BROADCAST
Permite el uso de envío broadcast en un socket
Sólo se puede usar con sockets UDP
UDP_NOCHECKSUM
Envío de checksum con valor 0 (no calcular)
IPPROTO_UDP
Tema 2: Interfaz socket
39
Interfaz socket – Sistema Windows
z
En Mircosoft Windows, la interfaz socket se denomina
Windows Socket o WinSock.
–
–
z
Librería de funciones de socket: DLL (dynamic linked
library), cargada en la memoria principal sólo cuando se
usa por primera vez (Windows 3.1)
Conjunto de Llamadas al Sistema (Windows 95 o Windows
NT)
La especificación WinSock define una interfaz de
programación basada en los sockets BSD de Unix. Se
compone de
–
–
–
rutinas estilo BSD Unix,
rutinas de bases de datos
y un conjunto de extensiones específicas de Windows
(para soportar la naturaleza del S.O. Windows: orientada
a mensajes – message driven).
Tema 2: Interfaz socket
40
Interfaz socket – Sistema Windows
z
Desviaciones respecto al Socket de Berkeley
–
Diferencia en los descriptores de ficheros
z
UNIX: signed int
–
z
Windows: unsigned int
–
–
–
z
z
–
z
–
UNIX: llamada close()
Windows: función closesocket()
WinSock soporta el dominio TCP/IP para la comunicación entre procesos
en el mismo ordenador o a través de la red. El dominio equivalente en
UNIX para a comunicación entre procesos es específico (PF_UNIX)
La librería debe ser inicializada y liberada en el programa principal:
z
–
UNIX: perror()
Windows: WSAGetLastError()
Para cerrar un socket
z
–
Error al crear un socket en Windows ⇒ devuelve INVALID_SOCKET
Los valores devueltos por las funciones son diferentes
Los mensajes de error son diferentes
z
–
Error al crear un socket en UNIX ⇒ devuelve -1
Inicio: WSAStartup().
Fin: WSACleanup ().
Diferencia en la API de select()
ioctlsocket() en lugar de ioctl() (modo no bloqueante: uso función
select())
Tema 2: Interfaz socket
41
Interfaz socket – Sistema Windows
z
WinSock Extensions
–
–
z
Las extensiones de WinSock se deben a la arquitectura message-driven de
Microsoft Windows.
Algunas de las extensiones se requieren para soportar la naturaleza de 16bit Windows 3.1 O.S (non-preempt).
Blocking vs. non-blocking
–
La mayor parte de las funciones de sockets de Berkeley tardan un tiempo
determinado: son bloqueantes.
z
–
Windows 3.1 no puede hacer lo mismo: los otros programas se ponen en
cola hasta la vuelta de la llamada bloqueada.
z
z
z
No supone un problema porque el scheduler de UNIX ordena la ejecución de
tareas y pone en ejecución otros trabajos (“preemption” de las tareas bloqueadas)
Por eso, las llamadas socket en Windows 3.1 se han diseñado no siendo
bloqueantes por defecto
Las llamadas usan la arquitectura basada en mensajes: Las colas de mensajes de
otras aplicaciones se van chequeando. Esto no es muy eficiente
WinSock Asynchronous functions
–
Funciones asíncronas especiales. Todas ellas empiezan con el prefijo
WSAAsync (orientadas al trabajo con ventanas)
Tema 2: Interfaz socket
42
Interfaz socket – Sistema Windows
z
Resumen de diferencias básicas sockets BSD UNIX-WinSock
–
Archivos de cabecera (header files): includes
–
Estructura WSAData e inicialización:
Tema 2: Interfaz socket
43
Interfaz socket – Sistema Windows
Tema 2: Interfaz socket
44
Interfaz socket – Sistema Windows
z
Resumen de diferencias básicas sockets BSD UNIX-WinSock
–
Finalización del programa
–
Informe de errores: WSAGetLastError() devuelve un entero que
indica el código del último error
Tema 2: Interfaz socket
45
Interfaz socket – Sistema Windows
z
Una forma de conseguir portabilidad…
Cabeceras…
En el programa principal…
#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
….
#include <stdio.h>
#include <string.h>
void main(int argc, char *argv[])
{
…..
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
…
Tema 2: Interfaz socket
#ifdef WIN32
WSACleanup ();
#endif
exit(0);
}
46
Programando se aprende…
Interfaz socket
z
Referencias…
–
BSD UNIX
z
z
z
–
- Inicio en la programación con
sockets (ejemplos)
- Pautas para el trabajo de la
asignatura y comienzo…
Lab 2.03
http://beej.us/guide/bgnet/
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unixsocket-faq.html
http://www.cs.rpi.edu/courses/sysprog/sockets/sock.html
WinSock
z
z
z
z
–
Sesiones de prácticas (6h)
http://msdn2.microsoft.com/en-us/library/ms741416.aspx
http://tangentsoft.net/wskfaq/
http://web.archive.org/web/20001025162345/www.sockaddr.com/index.html
http://www.sockets.com/
Utilidades
z
z
z
http://www.csee.usf.edu/~christen/tools/toolpage.html
http://williamstallings.com/DCC/DCC7e.html
Curso de C (unizar)
http://sicuz.unizar.es/siscen/documentacion.html
Tema 2: Interfaz socket
47
Descargar