Por: Benjamín Ginouvès S.
Para el Proyecto del ramo ELO330 Programación de Sistemas, 2º semestre 2010.
A través de este trabajo se busca centralizar la información para la programación de un sistema Cliente-Servidor, orientado a emplear las nuevas características de este protocolo SCTP.
La poca disponibilidad de programas demostrativos con utilización del protocolo SCTP con capacidades de conexión a través de múltiples enlaces a la red, esto es como por ejemplo por cable Ethernet y Wirelesss, ha llevado a que la migración desde el protocolo TCP a SCTP sea escaso.
Este proyecto pretende acercar un poco más los conceptos del protocolo SCTP mediante ejemplos escalables, en este caso un ejemplo del tipo eco, el se irá variando desde un simple programa con conexión TCP hasta una conexión con múltiples enlaces y múltiples streams.
Previamente a entrar de lleno a la programación del sistema Cliente-Servidor, realizaremos una breve descripción de las ventajas y desventajas de este protocolo, así como una breve introducción en el procedimiento que utiliza para entablar la conexión, y el envío de los paquetes de datos.
El protocolo SCTP (Stream Control Tranmission Protocol), es un nuevo protocolo para el control de la transmisión en la capa 4 del modelo TCP/IP, fue definido por el grupo SIGTRAN de IETF en el año 2000, está descrito en el RFC2960 (Stewart et al. 2000). Este protocolo es similar a los protocolos clásicos UDP y TCP, pero que reune las características de ambos protocolos para formar un nuevo y mejor protocolo de transmisión, además se le agregan otras funcionalidades prácticas como el multi-homing y el multi-streaming. A diferencia de TCP que esta era orientado a la conexión, el SCTP esta orientado a los mensajes como el protcolo UDP.
Los dos protocolos más populares de transmisión utilizados en al actialidad son el TCP y UDP, el protocolo TCP es confiable y garantiza el envío y la recepción ordenada de los segmentos manejando de una buena forma la congestión de la red, UDP es un protocolo no orientado a la conexión u orientado a la transmisión por lo que no garantiza el envío y la recepción ordenada ni la congestión de la red, sino que solo transmite los mensajes sin importar si estos llegan o no.
El protocolo SCTP es capaz de funcionar, para el modo multi-homing, a través de asociaciones conformando asociaciones para todos los enlaces, es decir, para el estableciemito de una conexión se agregan las direcciones de los enlaces al arreglo de salida o de entrada, dependiendo de se trata de una conexión del tipo one-to-many o many-to-one, estas conexiones pueden ser referidas tanto para varios enlaces entre máquinas o para el servicio a varios usuarios como el caso de UDP.
El paquete SCTP consiste de una cabecera común seguida de una pila de bloques llamados chunks, el número de chunks esta limitado por el MTU (Maximun Transfer Unit), estos chunks pueden contener datos de control o datos que se desean enviar de la aplicación específica.
La cabecera común consta de:
• La dirección del puerto de origen,
• La dirección del puerto de destino,
• El tag de verificación,
• El campo checksum del paquete,
Figura nº1. Formato de los paquetes de transmisión SCTP.
(Fuente: http://tdrwww.exp-math.uni-essen.de/inhalt/forschung/sctp_fb/pics/pdu.png)
Una conexión multi-homing se refiere a que es posible la conexión simultánea desde y hacia diferentes enlaces físicos de conexión, posibilitando una mayor velocidad de transmisión y/o una seguridad de enlaces, esto es como respaldo en caso de una pérdida de alguno de ellos.
Figura nº2. Esquema de conexión tradicional TCP versus una conexión multi-homing de SCTP
Una conexión realizada con el protocolo SCTP, es posible dividirla en varios streams, posibilitando la recepción en forma paralela de diferente información, que podría tratarse por ejemplo de un sitio web con su página html y los anexos como fotos, pudiendo presentar de forma más rápida el contenido de este al usuario.
Figura nº3. Esquema de una conexión con múltiples streams
El establecimiento de la conexión en el protocolo SCTP se realiza a través de 4-way handshake, lo que impide el bloqueo del servidor en cado de un ataque, por ejemplo el de denegación de servicio (DoS), debido a que el servidor sólo reservará la memoria del socket una vez se confirme la conexión, en la tercer comunicación, que también puede contener datos útiles.
Figura nº 4. Comparación del establecimiento de la conexión de TCP con SCTP.
Figura nº5 Comparación del encuadre de los mensajes entre TCP y SCTP/UDP
El protocolo SCTP, puede funcionar tanto como TCP en la entrega de los paquetes de forma ordenada, como de la forma UDP, sin orden establecido.
La desconexión del protocolo SCTP se basa en una intensión de cierre de conexión por alguno de los extremos, lo que lleva a el envío total de los datos restantes antes del acuse se cierre del extremo. Esto ayuda a que el extremo que estaba enviado información no envíe más información y ocupe ancho de banda si no hay un cliente que reciba los datos.
Figura nº6 comparación del esquema de desconexión entre TCP y SCTP, y modelo de término de conexión cunado hay datos pendientes
En el caso de la característica de SCTP de realizar multi-streaming, el protocolo TCP puede implementarlo mediante el uso de varios enlaces al cliente.
Para poder mostrar de mejor forma la evolución y migración de un programa Cliente-Servidor desde el protocolo TCP a SCTP, se programa un servidor del tipo iterativo que se encarga de realizar un eco o Echo para los datos recibidos desde el cliente.
Figura 7: diagrama de conexión entre el servidor (iterativo) y el cliente, para todos los caso a estudiar.
El método de conexión utilizado para el ejemplo se basa en la utilización principal de la estructura de conexión addrinfo, que reemplaza a la estructura sockaddr_in, permitiendo su utilización transparente tanto para conexiones del tipo IPv4 como IPv6, y ayudando a una muy pequeña variación entre el código de una conexión del tipo tradicional one-to-one (peer-to-peer), reduciéndose sólo al cambio de la descripción del protocolo de IPPROTOCOL_TCP a IPPTOTOCOL_SCTP.
Esto se puede apreciar en la migración desde el código ServidorEchoTCP.cpp y ClienteEchoTCP.cpp al código ServidorEchoSCTP.cpp y ClienteEchoSCTP.cpp, donde al no especificarse un protocolo por defecto en la estructura de addrinfo en conjunto con la función getaddrinfo() se asume un protocolo TCP. En el segundo caso se especifica el protocolo SCTP mediante la indicación explícita:
hints.ai_protocol = IPPROTO_SCTP;
Donde hints corresponde a la estructura del tipo addrinfo creada para la conexión del socket.
En ninguna medida pretendemos abarcar todos los comandos que se pueden utilizar en el protocolo SCTP, siendo este punto un punto de partida para la programación básica de éste protocolo. Se han omitido los comandos ya utilizados en los protocolos TCP y UDP, por lo que damos por entendido que son conocidos, y por lo que sólo serán nombrados.
#include <sys/types.h> #include <sys/socket.h> #include <netinet/sctp.h> int sctp_connectx(int sd, struct sockaddr * addrs, int addrcnt);
int sctp_bindx(int sd, struct sockaddr * addrs, int addrcnt, int flags);
int sctp_sendmsg(int sd, const void * msg, size_t len, struct sockaddr *to, socklen_t tolen, uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive, uint32_t context);
int sctp_send(int sd, const void * msg, size_t len, const struct sctp_sndrcvinfo *sinfo, uint32_t flags);
int sctp_recvmsg(int sd, void * msg, size_t * len, struct sockaddr * from, socklen_t * fromlen, struct sctp_sndrcvinfo * sinfo, int * msg_flags);
int sctp_peeloff(int sd, sctp_assoc_t assoc_id);
int sctp_getpaddrs(int sd, sctp_assoc_t assoc_id, struct sockaddr **addrs); void sctp_freepaddrs(struct sockaddr *addrs);
int sctp_getladdrs(int sd, sctp_assoc_t assoc_id, struct sockaddr **addrs); void sctp_freeladdrs(struct sockaddr *addrs);
int sctp_opt_info(int sd, sctp_assoc_t id, int opt, void * arg, socklen_t * size);
FALTA
El lenguaje de programación para el proyecto es C++, debido a que estos son ejemplos para dar una guía de cómo programar con el protocolo SCTP, no se ha incluido un archivo makefile, pero sería fácil de implementar, ya que se debe agregar sólo la librería sctp.
Antes de poder compilar los programas, debemos ver si está instalado el paquete fuente de encabezados para SCTP, esto se puede realizar de forma sencilla mediante la búsqueda en el gestor de paquetes con ‘sctp’ e instalarlo. Luego de este sencillo procedimiento podemos realizar la compilación como:
g++ -o ServidorEchoSCTP –lsctp ServidorEchoSCTP.cpp
Lo que nos generará el archivo ejecutable de nuestro servidor utilizando el protocolo SCTP.
Se incluyen los códigos de ejemplo para los siguientes casos:
Cliente-Servidor one-to-one con protocolo TCP:
ServidorEchoTCP.cpp Archivo con el código del servidor Echo con conexión TCP.
ClienteEchoTCP.cpp Archivo con el código del cliente Echo con conexión TCP.
Cliente-Servidor one-to-one con protocolo SCTP:
ServidorEchoSCTP.cpp Archivo con el código del servidor Echo con conexión SCTP.
ClienteEchoSCTP.cpp Archivo con el código del cliente Echo con conexión SCTP.
Cliente-Servidor one-to-one con protocolo SCTP, y establecimiento de multiples streams:
ServidorEchoSCTP_MS.cpp Archivo con el código del servidor Echo con conexión SCTP y configuración de multi-streams.
ClienteEchoSCTP_MS.cpp Archivo con el código del cliente Echo con conexión SCTP y configuración de multi-streams.
Cliente-Servidor one-to-one con protocolo SCTP, y establecimiento de multiples streams y envío de datos por uno de ellos: (*casos en desarrollo y perfeccionando el código)
ServidorEchoSCTP_MS2.cppArchivo con el código del servidor Echo con conexión SCTP y configuración de multi-streams, se intenta la transmisión de datos por uno de ellos.*
ClienteEchoSCTP_MS2.cpp Archivo con el código del cliente Echo con conexión SCTP y configuración de multi-streams, se intenta la transmisión de datos por uno de ellos.*
Debido al poco tiempo se dejó en espera el código para las conexiones del tipo multihoming, ya que el código de envío de datos por multistreams tuvo percances, los cuales se están perfeccionando
La ejecución del programa servidor se realiza de la siguiente forma:
./ServidorEchoXXX
./ClienteEchoXXX [Remote_Host]
Donde se indica con XXX el tipo de servidor y cliente que se quieren ejecutar. El puerto por defecto es el 12345, y puede ser cambiado en el código.
La realización de este proyecto comprendió el estudio de una nueva forma de comunicación, que a ciencia cierta será el recambio de los protocolos TCP y UDP que se utilizan actualmente, tanto por su versatilidad como protecciones de las que carecen los protocolos TCP y UDP.
Se encontró bastante información de la programación del protocolo SCTP referido al método normal de establecimiento de la conexión, a través del uso de la estructura sockaddr_in y las funciones inet_addr() y htons() para la configuración de la dirección y puertos de conexión. No obstante se debían crear dos opciones, una para una conexión con IPv4 y otra con IPv6. Esto se pudo omitir al utilizar la función getaddrinfo(), la que hace más transparente la configuración del socket de comunicación, enlazando a la estructura addrinfo la estructura sockaddr_in.
La información de la programación del protocolo SCTP utilizando la función getaddrinfo() no fue fácil, ya que no se encontró un ejemplo en internet de cómo era el procedimiento, por lo que se tuvo que estructurar uno para que las estructuras y reservas de memoria concordaran entre ambos procedimientos.
También se encontró que en el año 2007 persistía un error en la librería de getaddrinfo() con el que la compilación del código para su utilización con SCTP fallaba, esto pudo ser una de las posibilidades de que no se hayan realizado ejemplos de desarrollo con esta función. Esto ya ha sido solucionado en las versiones recientes.
Memoria de Tesis del Ingeniero Isaac Fernandez Bac, http://blog.pucp.edu.pe/item/21315/mi-tesis-sctp , imágenes.
http://www.kame.net/newsletter/19980604/
http://linux.die.net/man/3/sctp_connectx
http://www.frlp.utn.edu.ar/materias/internetworking/apuntes/SCTP/SCTP.pdf
Versión 1.0 - 03 Diciembre 2010.-