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