ASPECTOS DEL NIVEL DE TRANSPORTE

En nuestra sección de programación en red utilizamos un medio de transporte de la suite de protocolos de TCP/IP. Como ya experimentamos, nuestra aplicación usó directamente la capa de transporte, ya que en la mayoría de los protocolos las capas de sesión y presentación son inexistentes.

Servicios

Recordemos que el propósito de la capa de transporte es ofrecer servicios eficientes, confiables (si así lo pide el cliente) y expedito al nivel superior que casi siempre es la aplicación misma (nuestros programas en sockets cliente-servidor) o bien un servicio confiable (como el NFS, NetNews, FTP, Telnet y muchos más).

La capa de transporte ofrece servicios orientados y no orientados a la conexión, y pueden ser confiables o no confiables, y esto al parecer es lo mismo que ofrece la capa de red, excepto que el control de la capa de transporte es llevada a cabo en un nodo (computadora) particular y no en la subred. De tal manera podemos decir que de la capa de red para abajo tenemos una capa gigante llamada Proveedora de Servicio de Transporte, mientras que las superiores se pueden llamar Usuarios del Servicio de Transporte. También podemos decir que la capa de transporte es el límite entre nuestro proveedor de servicio de red física (subred) y el usuario final.

Aprovechando que la capa de transporte es el colchón entre la subred y la aplicación, la podemos ver como la capa que subsana las posibles deficiencias que la subred tiene para ofrecer un servicio que satisfaga a nuestras aplicaciones. Y la satisfacción va de la mano con la calidad, la cual se puede especificar en términos de los siguientes conceptos.

La capa de transporte en el emisor, a través de la de red, ejecuta un proceso de estira y afloja con su contraparte en el destino acordando los valores de los parámetros de calidad de servicio, lo cual se llama negociación de opciones.

Primitivas de la capa de transporte

La capa de transporte cuenta con una serie de primitivas que permiten crear aplicaciones. En nuestros programas de sockets ya experimentamos primitivas reales de la capa de transporte de TCP/IP.

 

Si revisamos nuestros programas del Apéndice A, nos daremos cuenta que siempre hubo una secuencia de operaciones con las primitivas que permitieron establecer la conexión, que båsicamente componen una negociación para crear una enlace "orientado a la conexión".

Control de flujo en la capa de transporte

Ya vimos que en la capa de enlace de datos se lleva a cabo en algunos modelos (o en la capa correspondiente) el control de flujo. El por qué se hace control de flujo en esta capa se explica porque si se le deja esta tarea únicamente a la capa de enlace, entonces es factible que un emisor más veloz que un receptor lento provoque que el receptor descarte paquetes porque no puede atenderlos, lo cual ya no lo va a saber el emisor porque la subred confirma que los paquetes fueron recibidos.

El control de flujo está basado en el uso de buffers en el emisor o receptor (o ambos) para almacenar todo aquél tráfico que excede la capacidad de procesamiento. Se recomienda que si la subred ofrece un servicio no confiable, el emisor tenga buffers con capacidad mayor o igual a R*C ( R por C), donde R es el tiempo de retraso promedio de entrega en la subred y C es la capacidad de transferencia de la subred. Por ejemplo, si la subred trabaja a C=10 Mbits/segundo y el retraso es 100 milisegundos (un retraso típico en una red nacional), entonces el buffer será mayor o igual a:

Buffer = .1 segundo * 10 Megabits/segundo = 1 Megabits = 125 Kilobytes

El manejo de este buffer se hace como de una ventana deslizante. La idea es enviar hasta C*R bits (en paquetes, o frames según sea la capa) y esperar a que se confirme la llegada de algunos de los paquetes enviados. Suponiendo que se confirmaron P paquetes, la ventana se deslizará hacia adelante P posiciones (que pueden ser de tamaño fijo o variable). Esto permite que se aproveche mejor la capacidad de la subred en lugar de estar enviando un paquete a la vez y esperar su confirmación. Además, si la subred ofrece servicios no orientados a la conexión, los paquetes pueden viajar cada uno por rutas diferentes y ser entregados en orden después

Direccionamiento

Otra características de la capa de transporte es que se requiere algún modo de direccionar o identificar de manera única cada conexión (el par de nodos interlocutores) o los paquetes que forman parte de una misma transmisión. En TCP/IP es una dirección IP y un número de puerto por cada nodo, en ATM es una par AAL-SAPs, y en general le llamaremos TSAP o PAST (Transport Service Access Point o Punto de Acceso al Servicio de Transporte). Los mismos puntos en la capa de red se llaman NSAP o PASR (Network Service Access Point o Punto de Acceso al Servicio de Red).

Los paquetes de control de flujo, de retransmisión de paquetes, etc. que intercambian dos entidades de la capa de transporte se llaman TPDU o UDPT (Transport Protocol Data Unit o Unidades de Datos del Protocolo de Transporte). Son paquetes especiales en cuanto que no tienen ningún significado para las capas física, de enlace, de red, de sesión, de presentación ni para la aplicación, solamente le importan a la capa de transporte porque con ellos van a efectuar las operaciones pertinentes a esta capa del modelo.

En nuestros programas de sockets, aprendimos que el direccionamiento de la capa de transporte (TCP) se especifica por un socket que consiste de una dirección IP y de un número de puerto que en nuestro caso fue el 50,000. En la comunidad de Internet, existen puertos que ya están reservados para ciertos servicios y hay otros puertos que se pueden usar a discreción por el programador de aplicaciones de red. Por ejemplo, el servicio TELNET se ofrece en el puerto 23, FTP en el 20 y 21, NetNews en el 119, SMTP en el 25, WWW en el 80, etc.

Por otro lado, es muy común que al programar en red se utilicen, en lugar del IP, el nombre del nodo al cual se desea conectarse, lo cual requiere que exista un mecanismo de resolución que nos entregue la dirección IP para el nombre especificado. Esa resolución la realiza el Servicio de Nombres de Dominios (DNS Domain Name Service), el cual revisaremos en la sección 8.8.2.

Para que quede una idea clara de las necesidades de direccionamiento único en la capa de transporte, observer en programa de sockets el procedimiento marca_numero( ), ahí observamos que se nos provee el nombre del nodo pero no su dirección IP, la cual resolvemos usando la función gethostbyname( ):

/* verificamos nombre */

if ((hp= gethostbyname(hostname)) == NULL) {

errno= ECONNREFUSED; /* y dirección */

return(-1); /* error, salimos */

}

Con la llamada anterior logramos construir el socket que necesita de la dirección IP (que es única a nivel mundial para cada nodo) y el puerto ya lo tenemos (que especifica un servicio único en ese nodo) y entonces tenemos un socket único a nivel mundial.

Protocolo TCP

El protocolo de control de transmisión (TCP en Inglés) fue diseñado para trabajar una capa de red no confiable, lo cual en un futuro, cuando se cuente con medios físicos de transmisión libres de errores no será necesario. Sin embargo, TCP tiene muchas más características que lo hacen robusto y práctico. TCP puede adaptarse a trabajar en redes con diferentes anchos de banda, topologías, tamaños de paquete, etc. TCP está descrito en los RFC 1122 y 1323 (Request for Comments).

La forma básica de trabajo de TCP es que la aplicación le pasa los datos a TCP, éste los toma en unidades menores a 64 Kb (la unidad más usada es 1.5 Kb que es el Maximum Transmission Unit de la mayoría de las tarjetas de red actuales) y se los pasa a IP. IP los toma y los envía (posiblemente por diferentes rutas) a la capa TCP en el destino, el cual los toma y reordena, re-ensambla, pide retransmisiones para aquellas unidades dañadas y entrega los datos a la aplicación destino como si no hubieran pasado por la subred, libres de errores.

El modelo de servicio de TCP

El servicio de TCP se ofrece permitiendo que el origen y destino establezcan sus puntos de comunicación llamados sockets, discutidos en la sección 5.3. El socket ya vimos que contiene la dirección del nodo y un número de puerto. El puerto de TCP (por ejemplo el 23 para telnet) es un TSAP (Transport Service Access Point). En un mismo socket se pueden establecer múltiples conexiones, cada conexión es identificada por el par (socket1, socket2). Los puertos cuyo número sea menor a 256 se les llama puertos bien conocidos (well known ports), y son descritos en el RFC 1700.

Todas las conexiones de TCP son full-duplex y punto a punto, TCP no soporta multicasting ni broadcasting.

El flujo de datos con TCP es similar a la concepción de lo que es un archivo en UNIX: un flujo de bytes sin ninguna estructura en particular, por esto, si se envían 2 mensajes de 128 bytes, estos pueden llegar al destino como tales o como un solo mensaje de 256 bytes.

Existen varias banderas que influyen en cómo trabaja TCP. Por ejemplo, existe la manera de decirle que los datos no sean almacenados en buffers en la capa de transporte, sino que los envíe de inmediato a la aplicación, también hay forma de indicarle que los datos son urgentes.

Un segmento de TCP se conforma de un encabezado de 20 bytes. Enseguida pueden ubicarse cero o más palabras de 32 bits de opciones, seguidas de hasta 65 Kb de datos. Si recordamos que el encabezado de IP consume 20 bytes, tenemos un consumo de 40 bytes de control contra 65 Kb de datos, lo cual nos da aproximadamente un 0.06% de sobrecarga de control. Los componentes del encabezado de TCP son como sigue.

Una conexión típica en TCP, donde N1=nodo 1, N2=nodo2, sería:

1. N1_SYN( SEQ=x ) -> N2

2. N2_SYN( SEQ=y, ACK=x+1 ) -> N1,

3. N1_SYN( SEQ=x+1, ACK=y+1 ) -> N2.

Esta plática se conoce como "three way handshake". En el intercambio de mensajes de control para crear y terminar una conexión, TCP puede caer en varios estados.

Control de congestión en TCP

La idea básica en el control de congestión es no intentar insertar un nuevo paquete en la red si es que uno anterior no la ha abandonado (se ha entregado). TCP logra la premisa anterior cambiando el tamaño de su ventana.

Cuando se inicia una conexión, el emisor manda segmentos de 1K, luego de 2K, luego de 4K y asi sucesivamente esperando una confirmación en cada caso. Cuando la confirmación falla, digamos en 2K, la ventana de congestión se pone de ese tamaño. A este proceso se le llama "comienzo lento".

Cada emisor tiene dos ventanas: la de congestión y la que confirma el receptor. Si el receptor dice "envíame segmentos de 4K" pero el emisor ya descubrió que esos segmentos no son confirmados porque rebasan la capacidad de la subred, pone su "ventana confirmada" en 4K y la de congestión en 2K, y finalmente enviará segmentos del tamaño que resulte menor de las dos ventanas, lo cual será la "ventana efectiva".

El algoritmo completo contiene otra ventana llamada "holgura" y sirve para afinar el crecimiento exponencial del algoritmo de comienzo lento. La ventana de holgura tiene un tamaño inicial de 64 Kb. cada vez que hay un timeout en el comienzo lento, el valor de la holgura será puesta al valor de la ventana de congestión dividido por dos, y el comienzo lento vuelve a arrancar, excepto que el crecimiento exponencial se detiene cuando se alcanza la holgura. De ahí en adelante la ventana de congestión crece de uno en uno.

Por ejemplo, supongamos que una subred puede procesar hasta 12 Kb. Inicialmente la ventana de congestión es 1K, la de confirmación es 0 y la de holgura es 64 K. El emisor inicia el comienzo lento y envía un paquete de 1 K, y el receptor le dice "mándame 24K". El emisor pone la de congestión en 1K, la confirmada en 24K y la holgura en 64K y envía un paquete de 2K. El receptor dice "envíame 24K. El emisor pone la de congestión en 2K y envía un paquete de 4K y obtiene la misma respuesta del receptor. El emisor pone la de congestión en 4K y envía un segmento de 8K, obtiene la misma respuesta y cambia la ventana de congestión a 8K y envía un segmento de 16K, pero como la subred solo soporta 12K, ocurre un timeout y tiene que poner su ventana de holgura a la mitad de la de congestión, es decir, a 4K y reinicia la de congestión a cero. Repite el comienzo lento hasta que su segmento enviado es de 4K, en ese momento su siguiente paquete no será de 8K, sino de 5K, luego de 6,7,8,9,10,11,12,13K donde habrá un timeout y se sabrá que el tamaño de ventana efectiva es de 12K.

Protocolo UDP

El protocolo UDP es simplemente el protocolo IP con un encabezado adicional y es muy útil para aquellas aplicaciones que trabajan en una red de área local donde se supone que la tasa de errores es despreciable, o bien donde la infraestructura de redes mayores (MAN,WAN,etc.) ofrece una capa de red con pocos errores.

El protocolo UDP está descrito en el RFC 768. Un paquete de UDP está compuesto de un encabezado de 8 bytes y datos. Los puertos oriígen y destino tienen la misma función que en TCP. El campo de la cadena de chequeo es opcional ya que la calidad de los datos entregados no importa, sólo importa que el paquete en sí sea entregado; por lo tanto se le deja la tarea de chequeo a la aplicación.