1x3 - Grupo ARCO
Transcripción
1x3 - Grupo ARCO
Versión 28/02/11 :: Redes :: aplicación transporte red Redes : : Transporte enlace física Capa de transporte TCP/IP 1 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Contenidos Introducción Protocolo de Datagramas de Usuario (UDP) Protocolo de Control de Transporte (TCP) Sockets BSD Redes : : Transporte Servidores y Clientes para el servicio UPPER 2 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Introducción La capa de transporte es el corazón de toda la jerarquía de protocolos. Es la que realmente ofrece servicios de valor a los usuarios Redes : : Transporte y aplicaciones. capas superiores Usuario del servicio de transporte transporte red enlace Proveedor del servicio de transporte física David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 3 Introducción La capa de transporte se encarga de proveer: ● Comunicaciones entre procesos. ● Mecanismos de control de flujo. ● Mecanismos de control de errores. ● Establecimiento de conexiones Redes : : Transporte La capa de transporte en Internet ofrece dos tipos de servicios a la capa de aplicación: ● No orientados a conexión (con UDP) ● Orientados a conexión (con TCP) 4 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Direccionamiento de procesos :: puertos La capa de red se encarga de la comunicación host a host, mientras que los protocolos de transporte realizan comunicación proceso a proceso (multiplexación) La IP identifica una interfaz de red de un host. Un puerto identifica un proceso en la máquina. Redes : : Transporte El puerto es un número de 16 bits: ● 0 – 1.023: “Bien conocidos” ● 1.024 – 49.151: Registrados ● 49152 – 65-535: Dinámicos entidades de transporte (procesos) P1 P2 Nota P3 P4 transporte red enlace física La La asignación asignación oficial oficial de de puertos puertos está está disponible disponible en: en: http://www.iana.org/assignments/port-numbers http://www.iana.org/assignments/port-numbers David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 5 Servicio NO orientado a conexión en la capa de transporte Una aplicación puede enviar paquetes de datos, incorporando una dirección destino en cada paquete. La aplicación receptora los recibirá como entidades separadas, de modo que la información debe manejarse mensaje por mensaje. Redes : : Transporte Este servicio resulta adecuado para aplicaciones que deben manejar muchos mensajes pequeños y de tamaño acotado. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 6 UDP (User Datagram Protocol) RFC RFC 768 768 Es un protocolo que ofrece un servicio no orientado a conexión No garantiza la entrega de mensajes No garantiza el orden ni evita la duplicidad de mensajes. Redes : : Transporte El protocolo realiza una multiplexación del tráfico IP para que pueda ser manejado por varias aplicaciones concurrentes. También hace un control de errores básico. El direccionamiento de procesos, en un mismo host, se realiza por medio de un identificador de 16 bits llamado puerto UDP. 7 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ UDP :: Cabecera 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 puerto UDP origen (opcional) longitud del mensaje UDP (completo) puerto UDP destino checksum (opcional) cuerpo del mensaje Redes : : Transporte Si se indica el puerto fuente es para que el receptor pueda responder a la aplicación emisora, si lo necesita. El cksum IP sólo afecta a la cabecera IP. Si se quiere confiabilidad sobre los datos debe usarse el cksum UDP. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 8 Servicio orientado a conexión en la capa de transporte Se ofrece a la aplicación el interfaz de una conexión establecida extremo a extremo. Las aplicaciones disponen de uno a varios circuitos virtuales en los que la información transmitida se maneja como un flujo continuo de datos. Redes : : Transporte Lo suelen utilizar aplicaciones que necesitan intercambio de datos de tamaños indeterminados, sin tener que preocuparse de subdividirlos en mensajes. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 9 TCP (Transmission Control Protocol) RFC RFC 793 793 1122 1122 Es un protocolo que ofrece un servicio orientado a conexión. Garantiza la integridad del flujo de datos. Se encarga, de forma transparente, de control de flujo y congestión, pérdida, repetición y orden de paquetes, etc. Se encarga de la multiplexación del tráfico IP para que pueda ser manejado por varios aplicaciones concurrentes Redes : : Transporte El direccionamiento de procesos se realiza por medio de un identificador de 16 bits llamado puerto TCP. La unidad de datos se denomina: segmento 10 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP Las conexiones TCP son full duplex y punto a punto. TCP no soporta multicast ni difusión. Cada dato de la carga de un segmento TCP tiene su propio nº de secuencia de 32 bits. Utiliza un sistema de control de flujo de ventana deslizante ● Los mecanismos de confirmación de recepción y del control de la ventana son independientes. Redes : : Transporte La tasa de salida se controla mediante la ventana congestión, la ventana de recepción y el umbral. 11 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Cabecera 1 2 3 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 puerto TCP origen puerto TCP destino número de secuencia reservado URG ACK PSH RST SYN FIN número de acuse de recibo offset checksum ventana puntero urgente opciones relleno cuerpo del mensaje Redes : : Transporte número de secuencia: El número de secuencia del primer byte del segmento. Si SYN está activo, indica el número de secuencia inicial (n). Y el primer byte será n+1 acuse de recibo: Si ACK está activo, indica el número de secuencia del siguiente byte que espera recibir. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 12 TCP :: Cabecera offset: tamaño de la cabecera TCP (en palabras de 4 bytes). Indica donde comienzan la carga del segmento. URG: activa el puntero urgente ACK: activa el acuse de recibo PSH: indica que los datos entregarse inmediatamente. RST: sirve para rechazar un intento de conexión o resetear una conexión activa. SYN: Se usa para el establecimiento de conexiones. Junto al bit ACK sirve para el inicio de conexión de 3 vías. FIN: se utiliza para finalizar conexiones. Puede ser unidireccional o bidireccional. Redes : : Transporte ventana: Se usan en los segmentos ACK, indica cuantos bytes está dispuesto a aceptar el receptor. puntero urgente: Si URG está activo, es el puntero al primer byte urgente David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 13 TCP :: Opciones 1. Fin de opciones 2. Nop 3. Tamaño máximo de segmento. Indicado por el receptor durante la conexión. Se conoce como MSS (Maximum Segment Size) 4. Escala de ventana. Indica que se va a usar una ventana de 32 bits en lugar de 16. Se negocia en la conexión 5. SACK permitido. Reconocimiento selectivo activado 6. SACK. Reconocimiento de segmentos concretos Redes : : Transporte 7. Marca de tiempo. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 14 TCP :: Servicio orientado a flujo En una conexión TCP los datos no se agrupan en unidades independientes como en UDP. Redes : : Transporte En TCP el proceso emisor produce el flujo de bytes y el receptor lo consume. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 15 TCP :: Buffers de envío y recepción Dado que el emisor no emite datos a la misma velocidad que el receptor los consume es necesario utilizar “buffers”. Nota proceso emisor Los Los datos datos no no se se envían envían byte byte aa byte byte sino sino en en grupos grupos llamados llamados Redes : : Transporte buffer de envío vacío por enviar enviado, no confirmado recibido, no procesado segmentos, segmentos, que que pueden pueden ser ser de de tamaño tamaño arbitrario arbitrario buffer de recepción proceso receptor David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 16 TCP :: Numeración de bytes Los números de secuencia de TCP identifican cada byte de la conexión. TCP no numera los segmentos. ● sequence number ● acknowledgement number Cada extremo utiliza una numeración independiente. El primer número de secuencia es aleatorio, no tiene porqué ser 0. Redes : : Transporte Estos números de secuencia se utilizan en los mecanismos de control de flujo y errores. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 17 TCP :: Numeración de bytes Números de secuencia: El valor de este campo de la cabecera TCP corresponde al primer byte de la carga del segmento. Números de acuse de recibo (reconocimiento): Redes : : Transporte El valor del campo TCP indica cual es el número de secuencia del siguiente byte que este extremo espera recibir. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 18 TCP :: Control de flujo TCP utiliza un protocolo de ventana deslizante. Ventana de recepción: Su tamaño indica cuántos bytes caben todavía en el buffer de recepción. Puede cambiar durante la conexión. ● Ventana de envío: Indica qué bytes del buffer de envío se pueden enviar en cada momento sin tener que esperar una confirmación. ● Redes : : Transporte Nota La La ventana ventana de de envío envío no no debe debe ser ser mayor mayor que que la la proceso emisor de de recepción recepción ventana de envío buffer de envío 27 26 25 24 23 22 21 20 19 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Deslizamiento de la ventana Partiendo del estado anterior, se recibe un segmento con los siguientes datos: ● acuse de recibo: 22 ● tamaño de ventana: 6 El buffer de envío queda: Redes : : Transporte proceso emisor ventana de envío buffer de envío 29 28 27 26 25 24 23 22 20 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Aumento de la ventana Partiendo del estado anterior, el emisor envía 3 bytes [23-25] y recibe un segmento con los siguientes datos: ● acuse de recibo: 24 ● tamaño de ventana: 8 El buffer de envío queda: Redes : : Transporte proceso emisor ventana de envío buffer de envío 31 30 29 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 28 27 26 25 24 21 TCP :: Reducción de la ventana Partiendo del estado anterior, el emisor envía 2 bytes [26-27] y recibe un segmento con los siguientes datos: ● acuse de recibo: 28 ● tamaño de ventana: 5 El buffer de envío queda: Redes : : Transporte proceso emisor ventana de envío buffer de envío 35 34 33 32 31 30 29 28 22 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Cierre de la ventana Se produce cuando el receptor no está dispuesto a aceptar nada de tráfico. Se recibe un segmento con los siguientes datos: ● acuse de recibo: 28 ● tamaño de ventana: 0 El buffer de envío queda: ventana de envío cerrada Redes : : Transporte proceso emisor buffer de envío 35 34 29 33 32 31 30 29 28 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Síndrome de la ”ventana tonta” 23 RFC RFC 896 896 Ocurre cuando cada acuse de recibo anuncia una pequeña cantidad de espacio disponible y por tanto cada nuevo segmento es pequeño, desperdiciando recursos en la red y en los hosts. Prevención: ● Redes : : Transporte ● Cuando el receptor cierra la ventana, debe esperar a tener una cantidad considerable de espacio antes de volver a abrirla. El emisor debe “esperar” a tener una cantidad adecuada de datos (clumping) antes de enviar un nuevo segmento. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 24 TCP :: Síndrome de la ”ventana tonta” Algoritmo de Nagle Si se generan nuevos datos pero no se han reconocido los anteriores, los nuevos se almacenan en el buffer de salida hasta que alcancen el MSS. Cuando llegue un acuse de recibo se puede enviar el contenido del buffer. Redes : : Transporte if hay nuevos datos para enviar: if el tamaño de ventana y los datos disponibles >= MSS: enviar un segmento completo de tamaño de MSS ahora else: if hay datos sin confirmar en espera: encolar los datos en el buffer hasta recibir un ACK else: enviar los datos ahora David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 25 TCP :: Control de errores TCP garantiza la entrega de todo el flujo de datos: ● manteniendo el orden de los datos ● sin errores ● sin partes ausentes o duplicadas Redes : : Transporte El control de errores incluye detección de segmentos: ● corruptos ● fuera de orden ● perdidos ● duplicados También incluye los mecanismos de corrección una vez detectados estos errores. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 26 TCP :: Control de errores El receptor de un segmento comprueba el checksum: ● Si es correcto, envía al emisor un acuse de recibo. ● Si es incorrecto, descarta el segmento. El emisor inicia un temporizador al enviar cada segmento Redes : : Transporte ● Si no llega un acuse de recibo antes de que el temporizador expire, se reenvía el segmento correspondiente David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 27 TCP :: Control de errores segmento corrupto o perdido timer timer timer emisor receptor 1 seq: 1201 , 200B 2 seq: 1401 , 200B 3 seq: 1601 , 200B segmento corrupto o perdido 01 ack: 16 3 timer Redes : : Transporte timeout retransmi seq: 1601 , 200B 0 ack: 18 sión 1 28 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Control de errores acuse de recibo corrupto o perdido timer timer timer emisor receptor 1 seq: 1201 , 200B 2 seq: 1401 , 200B 3 seq: 1601 , 200B 0 ack: 16 Redes : : Transporte 0 ack: 18 1 1 29 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Control de errores segmento duplicado receptor 1 seq: 1201 , 200B 2 seq: 1401 , 200B 3 seq: 1601 , 200B timer timer timer emisor 0 ack: 16 1 01 ack: 18 timer Redes : : Transporte timeout 3 acuse perdido o llega después del timeout retransmi seq: 1601 , 200B 0 ack: 18 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ sión descartar 1 30 TCP :: Control de errores segmento fuera de orden Redes : : Transporte timer timer timer emisor receptor 1 seq: 1201 , 200B 2 seq: 1401 , 200B 3 seq: 1601 , 200B 0 ack: 14 1 0 ack: 18 1 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 31 TCP :: Temporizadores TCP utiliza 4 temporizadores: Retransmisión Persistencia “Keep alive” Redes : : Transporte Fin de conexión David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 32 TCP :: Temporizador de retransmisión Es el temporizador utilizado para retransmitir segmentos cuando no llega el acuse de recibo correspondiente. Este temporizador es diferente en cada conexión y cambia durante una misma conexión. Se recalcula cada vez que se recibe un acuse de recibo: 2 x RTT El RTT se puede calcular con: ● la opción “marca de tiempo” ● enviando un segmento y midiendo el tiempo hasta el acuse Redes : : Transporte RTT = α x RTT previo + (1 - α) x RTT actual Los acuses de recibo de segmentos retransmitidos no se tienen en cuenta en este cálculo (Algoritmo de Karn). David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 33 TCP :: Temporizador de Persistencia Cuando el emisor recibe un mensaje de cierre de la ventana queda en espera de un nuevo acuse indicando la apertura. Si ese acuse se pierde, los dos extremos de la conexión quedan bloqueados. Para evitar esto, el emisor inicia un temporizador y cuando expira envía un segmento especial de prueba para que el receptor le informe del estado de su ventana. Redes : : Transporte El valor de este temporizador empieza siendo igual al de retransmisión pero se duplica cada vez, hasta un máximo de 60s. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 34 TCP :: Temporizador “Keep Alive” Este temporizador se utiliza para evitar que una conexión quede abierta indefinidamente. El servidor inicia el temporizador con un valor de 2 horas. Cada vez que recibe un segmento del cliente, reinicia el temporizador Redes : : Transporte Si el temporizador expira, el servidor envía una prueba al cliente. Si después de 10 pruebas enviadas cada 75 s, el cliente no contesta, el servidor cierra la conexión. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 35 TCP :: Temporizador de fin de conexión Cuando se cierra una conexión, ésta queda en un estado de “limbo” durante un periodo de tiempo dado por este temporizador. Su valor es normalmente el doble del tiempo de vida de un segmento. Redes : : Transporte Cuando el temporizador expira se finaliza realmente la conexión y se recicla el puerto asignado. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 36 TCP :: Control de congestión Si la red descarta paquetes porque está congestionada y los emisores retransmiten esos paquetes, la congestión se agravará aún más. TCP asume que la perdida de paquetes está causada siempre por la congestión. Redes : : Transporte De modo que el tamaño de la ventana de emisión está dado por: ● El tamaño de ventana permitido por el receptor. ● El tamaño de la ventana de congestión. ventana de envío = mínimo (ventana del receptor, ventana de congestión) 37 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Prevención de la congestión Arranque lento: ● ● ● En el arranque, el tamaño de la ventana de congestión es MSS Por cada segmento reconocido se incrementa el tamaño de la ventana de congestión en MSS bytes Esto ocurre hasta que el tamaño de la ventana de congestión alcanza la mitad del tamaño máximo de la ventana. Aumento aditivo: ● Redes : : Transporte ● Una vez alcanzado el umbral anterior, la ventana de congestión aumenta en MSS por cada acuse recibido, aunque el acuse corresponda a varios segmentos. Este crecimiento continúa hasta que el tamaño de la ventana de congestión alcance el umbral, cuyo valor es igual a la ventana de recepción. Nota Todo Todo lo lo anterior anterior sólo sólo es es aplicable aplicable si si los los acuses acuses de de recibo recibo llegan llegan antes antes de de que que expiren expiren los los temporizadores temporizadores correspondientes correspondientes 38 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: Prevención de la congestión Disminución multiplicativa: ● ● Se aplica cuando expira un temporizador de retransmisión, aunque ello ocurra durante el proceso de arranque lento o el aumento aditivo. Consiste en situar el umbral a la mitad de la ventana de congestión anterior y comenzar de nuevo con un arranque lento. tamaño de ventana de congestión Redes : : Transporte timeout umbral umbral segmentos David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 39 TCP :: establecimiento de conexión Cada extremo debe obtener permiso del otro extremo antes de comenzar la transmisión de datos. Un extremo tiene un rol activo (cliente) y el otro pasivo (servidor). Triple “apretón de manos”: cliente servidor SYN seq: 1200 , ac k: - ACK SYN + Redes : : Transporte 00 seq: 48 , ack: 1 2. El servidor confirma, indica su ISN y otros datos de conexión 201 3. El cliente confirma y puede enviar datos en ese segmento ACK seq: 1201 , ac 1. El cliente indica su ISN (Initial Sequence Number) y otros parámetros de conexión como el MSS k: 4801 40 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ TCP :: desconexión Cualquiera de los extremos puede indicar al otro que ya no desea enviar más datos en esa conexión. Cuadruple “apretón de manos”: A B 2. B confirma que la comunicación A->B queda cerrada. B puede seguir enviando. FIN seq: 2500 , ac ACK 00, ack seq: 70 Redes : : Transporte FIN + A 01 seq: 70 CK k: - : 2501 , ack: 2 3. Cuando B termine indica a A que ya no le va a enviar más datos. 501 ACK seq: 2501 , ac 1. A indica a B que ya no le va a enviar más datos, pero seguirá recibiendo. k: 7002 4. A confirma la petición de B David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 41 Redes : : Transporte TCP :: Conexión/Desconexión +---------+ ---------\ active OPEN | CLOSED | \ ----------+---------+<---------\ \ create TCB | ^ \ \ snd SYN passive OPEN | | CLOSE \ \ ------------ | | ---------\ \ create TCB | | delete TCB \ \ V | \ \ +---------+ CLOSE | \ | LISTEN | ---------- | | +---------+ delete TCB | | rcv SYN | | SEND | | ----------| | ------| V +---------+ snd SYN,ACK / \ snd SYN +---------+ | |<---------------------------------->| | | SYN | rcv SYN | SYN | | RCVD |<-----------------------------------------------| SENT | | | snd ACK | | | |------------------------------------| | +---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+ | -------------| | ----------| x | | snd ACK | V V | CLOSE +---------+ | ------| ESTAB | | snd FIN +---------+ | CLOSE | | rcv FIN V ------| | ------+---------+ snd FIN / \ snd ACK +---------+ | FIN |<---------------------------------->| CLOSE | | WAIT-1 |-----------------| WAIT | +---------+ rcv FIN \ +---------+ | rcv ACK of FIN ------| CLOSE | | -------------snd ACK | ------- | V x V snd FIN V +---------+ +---------+ +---------+ |FINWAIT-2| | CLOSING | | LAST-ACK| +---------+ +---------+ +---------+ | rcv ACK of FIN | rcv ACK of FIN | | rcv FIN -------------- | Timeout=2MSL -------------- | | ------x V -----------x V \ snd ACK +---------+delete TCB +---------+ ------------------------>|TIME WAIT|------------------>| CLOSED | +---------+ +---------+ David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 42 Sockets TCP / UDP Las aplicaciones que quieran manejar tráfico deben utilizar una dirección IP (para direccionar un host) y un puerto (para direccionar un proceso) La tupla (IP, puerto) se denomina socket. Una conexión se identifica con un par de sockets: (socket1, socket2) Los segmentos TCP y UDP se encapsulan sobre datagramas IP. La cabecera IP indica la IP, la cabecera TCP o UDP indica el puerto. Segmento TCP o UDP Redes : : Transporte cabecera cabecera IP cabecera de trama datos área de datos IP área de datos de la trama terminador de la trama 43 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Programación con Sockets BSD Un socket es un extremo en una conexión de red. Los sockets son el API que permite utilizar los servicios de la capa de transporte. La interfaz de sockets original era parte de Unix BSD, por lo que se les suele llamar sockets BSD. Redes : : Transporte En los sistemas Unix se implementan como llamadas al sistema, cuyo tratamiento es muy similar al de los ficheros convencionales. 44 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Sockets :: Tipos Aplicación Aplicación Stream sockets TCP TCP Datagram sockets “raw” sockets UDP UDP Redes : : Transporte IP IP A parte de los sockets STREAM y DGRAM es habitual disponer de otros tipos de sockets como RAW o UNIX Los sockets RAW suelen requerir privilegios especiales. Capas Capas inferiores inferiores David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 45 Sockets :: Ordenamiento de bytes Los computadores pueden optar por dos tipos de ordenamiento: big-endian (Motorola) o little endian (Intel) También es una característica de los protocolos de red. Los protocolos de la pila TCP/IP usan big-endian. Redes : : Transporte Se necesitan funciones para convertir el ordenamiento del computador al de la red. ● htons() - host to network short (16 bits) ● htonl() - host to network long (32 bits) ● ntohs() - network to host short ● ntohl() - networt to host long David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 46 Sockets :: Transformación de direcciones También se dispone de funciones para transformar direcciones IP en su representación ASCII utilizando Redes : : Transporte números decimales con puntos ● inet_aton() - Dirección en ASCII a formato binario ● inet_ntoa() - de formato binario a dirección en ASCII David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 47 Sockets EL API de sockets BSD al igual que todas las llamadas al sistema Unix están implementadas como funciones C. Redes : : Transporte Por simplicidad, pero sin perdida de generalidad, nosotros veremos la librería de sockets de Python, que no es más que un wrapper de las llamadas al sistema C David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 48 Clase Socket En Python los sockets son objetos, cuyo constructor es: socket(familia, tipo, [proto]) ● familia: AF_INET, AF_INET6, AF_UNIX, AF_PACKET,etc ● tipo: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW ● proto: En caso de que el tipo dado permita varios protocolos. Redes : : Transporte En el caso de IPv4 se utiliza AF_INET con SOCK_DGRAM para UDP y SOCK_STREAM para TCP. SOCK_RAW permite construir paquetes directamente sobre el nivel de enlace o tramas sobre el nivel físico. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 49 Clase Socket bind(address) - Vincula el socket a una dirección. ● address: El formato depende de la familia de socket. En el caso de AF_INET es una tupla (host, puerto). connect(address) Si se utiliza STREAM conecta el socket local al socket remoto que está en la dirección indicada. Si se utiliza DGRAM indica cual es el destino y origen por defecto de los datagramas. listen(backlog) Redes : : Transporte backlog Indica cuantos clientes como máximo quedarán a la espera. Las demás conexiones serán rechazadas. Sólo tiene sentido en STREAM David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 50 Clase Socket accept() - Acepta una nueva conexión. Sólo STREAM. Devuelve una tupla (conn, address): conn: Es un socket recién creado para materializar la conexión con el cliente remoto. address: La dirección del otro extremo de la conexión (el cliente) send(data, [flags]) - Envía data al socket remoto. Si es un socket DGRAM envía a la dirección indicada en el connect(). Devuelve la cantidad de bytes recibidos. recv(size, [flags]) - size es la cantidad de bytes que se Redes : : Transporte desean leer. Devuelve los datos recibidos. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 51 Clase Socket sendto(data, [flags], address) - Envía data al socket indicado en address. Sólo se puede utilizar con sockets DGRAM. recvfrom(size, [flags]) - size es la cantidad de bytes que se desean leer. Devuelve una tupla (data, address): data: Son los datos recibidos address: Es la dirección del socket que ha enviado el datagrama Sólo tiene sentido para sockets DGRAM. shutdown(how) – Permite cerrar una conexión (STREAM) de forma Redes : : Transporte unidireccional o bidireccional close() – Cierra la conexión (si la hay) y libera los recursos del socket 52 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Sockets como ficheros El API de sockets en C tiene funciones read() y write() completamente compatibles con las que se utilizan sobre ficheros. En Python, la clase socket no dispone de esos métodos, ni se le pueden aplicar directamente otros funciones como flush(). Sin embargo, dispone de dos métodos para obtener el manejador de fichero asociado al socket. ● fileno() retorna el descriptor entero de fichero asociado al socket. ● makefile() retorna un objeto de clase fichero asociado al socket. Redes : : Transporte El paquete socket también dispone de la función fromfd() que permite obtener un objeto socket a partir de un manejador de fichero 53 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Esquema cliente/servidor UDP Servidor UDP socket() Clientes UDP socket() bind() sendto() recvfrom() procesamiento recvfrom() Redes : : Transporte sendto() close() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 54 Cliente UDP #!/usr/bin/python "Usage: %s <server> <port>" Listado Completo from sys import argv, exit from socket import * if len(argv) != 3: print __doc__ % argv[0] exit(1) sock = socket(AF_INET, SOCK_DGRAM) Redes : : Transporte while 1: data = raw_input() if not data: break # acaba con '' sock.sendto(data, (argv[1], int(argv[2]))) msg, server = sock.recvfrom(1024) print "La respuesta es '%s'" % msg sock.close() 55 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor UDP básico (síncrono) Listado Completo #!/usr/bin/python "Usage: %s <port>" if len(argv) != 2: print __doc__ % argv[0] exit(1) from sys import argv, exit from socket import * import time sock = socket(AF_INET, SOCK_DGRAM) sock.bind(('', int(argv[1]))) JOB = 1 Redes : : Transporte def handle(sock, msg, client, n): print 'New request', n, client time.sleep(JOB) # some job sock.sendto(msg.upper(),client) n = 0 while 1: msg, client = sock.recvfrom(1024) n += 1 handle(sock, msg, client, n) 56 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor UDP :: un proceso por petición (I) #!/usr/bin/python "Usage: %s <port>" Listado Completo from sys import argv, exit import socket import os, time MAX_CHILDREN = 40 JOB = 1 Redes : : Transporte def handle(sock, msg, client, n): print 'New request', n, client time.sleep(JOB) # some job sock.sendto(msg.upper(),client) def collect_children(children): while children: if len(children) < MAX_CHILDREN: opts = os.WNOHANG else: opts = 0 pid, status = os.waitpid(0, opts) if not pid: break children.remove(pid) David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ if len(argv) != 2: print __doc__ % argv[0] exit(1) sock= socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', int(argv[1]))) n = 0 children = [] while 1: msg, client = sock.recvfrom(1024) n += 1 collect_children(children) pid = os.fork() if pid: children.append(pid) else: handle(sock, msg, client, n) exit() 57 Servidor UDP :: un hilo por petición Listado Completo if len(argv) != 2: print __doc__ % argv[0] exit(1) #!/usr/bin/python "Usage: %s <port>" sock = socket(AF_INET, SOCK_DGRAM) sock.bind(('', int(argv[1]))) from sys import argv, exit from socket import * import thread, threading, time lock = threading.Lock() JOB = 1 Redes : : Transporte def handle(sock, msg, client, n): print 'New request', n, client time.sleep(JOB)# some job n = 0 while 1: msg, client = sock.recvfrom(1024) n += 1 thread.start_new_thread(handle, (sock, msg, client, n)) lock.acquire() try: sock.sendto(msg.upper(), client) except error, e: print e, client lock.release() 58 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor UDP :: SocketServer.UDPServer Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from SocketServer import * import time JOB = 1 Redes : : Transporte class UpperHandler(DatagramRequestHandler): def handle(self): print 'New request:', self.client_address msg = self.rfile.read().upper() time.sleep(JOB) self.wfile.write(msg) if len(argv) != 2: print __doc__ % argv[0] else: UDPServer(('', int(argv[1])), UpperHandler).serve_forever() 59 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor UDP :: SocketServer.ForkingUDPServer (Un proceso por petición) Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from SocketServer import * import time JOB = 1 Redes : : Transporte class UpperHandler(DatagramRequestHandler): def handle(self): print 'New request:', self.client_address msg = self.rfile.read().upper() time.sleep(JOB) self.wfile.write(msg) if len(argv) != 2: print __doc__ % argv[0] else: ForkingUDPServer(('', int(argv[1])), UpperHandler).serve_forever() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 60 Esquema cliente/servidor TCP socket() bind() listen() Creación de un proceso, hilo o gestión asíncrona accept() socket() connect() send() Servidor TCP Padre recv() Redes : : Transporte recv() trabajo close() send() Cliente TCP close() Servidor TCP Hijo 61 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Cliente TCP Listado Completo #!/usr/bin/python "Usage: %s <server> <port>" from sys import argv, exit from socket import * if len(argv) != 3: print __doc__ % argv[0] exit(1) sock = socket(AF_INET, SOCK_STREAM) sock.connect((argv[1],int(argv[2]))) while 1: data = raw_input() if not data: break # acaba con '' sent = sock.sendall(data) msg = '' while len(msg) < sent: msg += sock.recv(32) print "La respuesta es '%s'" % msg Redes : : Transporte sock.close() 62 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor TCP básico Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from socket import * import time Redes : : Transporte JOB = 1 def handle(sock, client): print 'Client connected:', client while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) sock.close() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ if len(argv) != 2: print __doc__ % argv[0] exit(1) sock = socket(AF_INET, SOCK_STREAM) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(('', int(argv[1]))) sock.listen(5) while 1: child_sock, client = sock.accept() handle(child_sock, client) 63 Servidor TCP :: un proceso por conexión (I) Listado Completo def collect_children(children): while children: if len(children) < MAX_CHILDREN: opts = os.WNOHANG else: opts = 0 #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit import socket import os, time pid, status = os.waitpid(0, opts) if not pid: break children.remove(pid) Redes : : Transporte MAX_CHILDREN = 40 JOB = 1 def handle(sock, client, n): print 'Client connected', n, client while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) sock.close() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 64 Servidor TCP :: un proceso por conexión (II) if len(argv) != 2: print __doc__ % argv[0] exit(1) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('', int(argv[1]))) sock.listen(5) n = 0 children = [] while 1: child_sock, client = sock.accept() n += 1 Redes : : Transporte collect_children(children) pid = os.fork() if pid: children.append(pid) else: handle(child_sock, client, n) exit() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 65 Servidor TCP :: un hilo por conexión Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from socket import * import thread, time Redes : : Transporte JOB = 1 if len(argv) != 2: print __doc__ % argv[0] exit(1) sock= socket(AF_INET, SOCK_STREAM) sock.bind(('', int(argv[1]))) sock.listen(5) n = 0 while 1: child_sock, client = sock.accept() n += 1 thread.start_new_thread(handle, (child_sock, client, n)) def handle(sock, client, n): print 'Client connected', n, client while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) sock.close() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 66 Servidor TCP asíncrono :: select() Listado Completo def ParentHandler(s): child_sock, client = s.accept() socks.append(child_sock) print 'Client connected:', client #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from socket import * import select, time JOB = 1 socks = [ss] def ChildHandler(s): data = s.recv(32) if not data: s.close() socks.remove(s) return Redes : : Transporte ss = socket(AF_INET, SOCK_STREAM) ss.bind(('', int(argv[1]))) ss.listen(5) while 1: rd = select.select(socks, [], [])[0] time.sleep(JOB) # some job s.sendall(data.upper()) for i in rd: if i == ss: ParentHandler(i) else: ChildHandler(i) 67 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor TCP :: SocketServer.TCPServer Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from SocketServer import * import time JOB = 1 Redes : : Transporte class UpperHandler(StreamRequestHandler): def handle(self): print 'Client connected:', self.client_address while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) self.request.close() if len(argv) != 2: print __doc__ % argv[0] else: server = TCPServer(('',int(argv[1])), UpperHandler) server.serve_forever() 68 David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ Servidor TCP :: SocketServer.ForkingTCPServer (un proceso por conexión) Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from SocketServer import * import time JOB = 1 Redes : : Transporte class UpperHandler(StreamRequestHandler): def handle(self): print 'Client connected:', self.client_address while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) self.request.close() if len(argv) != 2: print __doc__ % argv[0] else: server = ForkingTCPServer(('',int(argv[1])), UpperHandler) server.serve_forever() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 69 Servidor TCP :: SocketServer.ThreadingTCPServer (un hilo por conexión) Listado Completo #!/usr/bin/python "Usage: %s <port>" from sys import argv, exit from SocketServer import * import time JOB = 1 Redes : : Transporte class UpperHandler(StreamRequestHandler): def handle(self): print 'Client connected:', self.client_address while 1: data = sock.recv(32) if not data: break time.sleep(JOB) # some job sock.sendall(data.upper()) self.request.close() if len(argv) != 2: print __doc__ % argv[0] else: server = ThreadingTCPServer(('',int(argv[1])), UpperHandler) server.serve_forever() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 70 Servidor TCP :: Paquete Asyncore #!/usr/bin/python "Usage: %s <port>" Listado Completo from sys import argv, exit from socket import * import asyncore, time JOB = 1 class ChildHandler(asyncore.dispatcher): def __init__(self, sock): asyncore.dispatcher.__init__(self, sock) self.buffer = '' def handle_read(self): self.buffer += self.recv(32) time.sleep(JOB) # some job Redes : : Transporte def writable(self): return (len(self.buffer) > 0) def handle_write(self): sent = self.send(self.buffer.upper()) self.buffer = self.buffer[sent:] def handle_close(self): self.close() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 71 Servidor TCP :: Paquete Asyncore (II) class ParentHandler(asyncore.dispatcher): def __init__(self): asyncore.dispatcher.__init__(self) self.create_socket(AF_INET, SOCK_STREAM) self.set_reuse_addr() self.bind(('', int(argv[1]))) self.listen(5) def handle_accept(self): child_sock, client = self.accept() print 'Client connected', client ChildHandler(child_sock) Redes : : Transporte ParentHandler() asyncore.loop() David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 72 Servidor de procesos Un servidor de procesos (o superservidor) es un programa especial que escucha en muchos puertos a la vez (TCP y UDP) para servicios de uso esporádico. Cuando hay una petición o conexión a alguno de esos puertos, el superservidor instancia un programa concreto para manejar ese servicio. Redes : : Transporte En GNU/Linux se llama inetd y se configura por medio del fichero /etc/inetd.conf David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 73 Servidor de procesos Ejercicio Redes : : Transporte Utilizando Python estándar, escribe un servidor de procesos que implemente internamente servidores de echo, daytime, time y discard tanto TCP como UDP. Y que pueda utilizar servidores externos estándar de ftp, tftp y telnet. David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 74 Referencias Se recomienda repasar y profundizar el contenido de este tema utilizando (al menos) la siguiente bibliografía básica: A.S. Redes de computadores. Pearson Educación, Cuarta edición, 2003. ● Capítulos 6. Apartados 1 - 5.10 CISCO Systems. Inc. Guía del primer año. CCNA 1 y 2. Cisco Press, 2003. ● Capítulos 9 y 19 Material e-learning CISCO CCNA Exploration Redes : : Transporte ● Nota Módulo 4 Todos los listados de este tema están disponibles para descarga en la dirección: https://arco.esi.uclm.es/svn/public/misc/python_networking/upper/ David Villa <[email protected]> :: http://www.inf-cr.uclm.es/www/dvilla/ 75