You are on page 1of 32

Instituto Profesional Cenafom Ramo : Transmisin de Datos Santiago, Octubre de 2000

Indice Introduccin 3 Dnde nos Movemos? 4 I Parte. Conceptos Bsicos de Redes 4 Protocolo de Comunicaciones 4 Capas de Red 4 Cliente y Servidor 6 IP Internet Protocol 6 TCP Transmission Control Protocol 7 UDP User Datagram Protocol 7 Direccin IP 8 Dominios 9 Puertos y Servicios 10 Cortafuegos (Firewall) 10 Servidores Proxy 10 URL Uniform Resource Locator 11 II Parte UNIX y los Sockets 11 2.1 Qu son los Sockets? 12 Tipos de Sockets 13 Stream Sockets y Datagram Sockets 14 Cmo creo un Socket? 16 Obtencin del Descriptor(Paso 1) 16 Direccin del Socket(Paso 2) 17 Opciones de Socket y Trabajo con Datagramas 19 Datagramas 21 Sendto 21 Recvfrom 21 III Parte Sockets Orientados a Conexin 22 3.1 El Servidor 22 3.2 Funcin Listen() 23 1

3.3 Funcin Accept() 23 3.4 El Cliente 25 3.5 Funcin Connect() 25 3.6 Funciones Close() y Shutdown() 26 3.7 Funcin Getpeername() 27 3.8 Funcin Gethostname() 27 3.9 Ultimos puntos a tener en cuenta 27 3.10 Seales ms importantes 28 3.11 Temporizaciones 29 3.12 Funcin Select() 30 3.13 Programa Servidor 30 3.14 Programa Cliente 32 Conclusiones 34 Bibliografa 35

Introduccin Debido al rpido avance de los cambios tecnolgicos que se suceden, muchas veces estos mismos no son muy claros para nosotros, pero al encontrarse fuera del mbito de nuestro trabajo, no nos damos el tiempo, ni la ocasin de investigarlos y, de esta manera, comprenderlos. Uno de estos sectores, cuya evolucin se ha hecho sentir con paso del tiempo, es la que concierne al desarrollo de los medios de comunicacin de datos y que se acrecienta si pensamos en los diferentes formatos que disponemos actualmente para lograr esta comunicacin. Si quisisemos lograr nosotros mismos una comunicacin sin problemas, Qu deberamos hacer?, Buscar entre los medios conocidos aquel que me d ms confiabilidad?, Usar lo que tengo y no crearme ms problemas?, Probar si es que puedo programar algo que me d solucin o, al menos, libere carga del problema?..Todas las posibles soluciones que se nos vendran a la mente estaran orientadas casi en un 90% a responder las dos primeras interrogantes, pero Por qu nos quedamos con un esculido 10% para intentar resolver la ltima?, Y la respuesta se cimienta por lo que comentamos al principio, desconocemos muchos de los detalles que involucran los procesos de envo y recepcin de informacin. Este trabajo se orienta, precisamente, al tratamiento de este problema. Mejorar nuestro conocimiento de uno de los principales elementos que nos sirven de enlace a la hora de traspasar informacin, los Sockets. Si bien es cierto que un acabado estudio de todo lo que debemos saber a la hora de comprender cabalmente su funcionamiento traera el enfrentarse con tomos de informacin de diferentes tpicos con rasgos en comn. Nuestro norte aqu ser remitirnos a saber: Qu es un Socket?, Cmo funciona?, Hay diferentes tipos de ellos?, Es posible que me cree yo mismo un Socket?, Existe algn tipo de restricciones en su uso? 2

Bueno este trabajo intentar despejar todas estas dudas y tratar de profundizar en aquellas reas en las que me sea posible, sin dejar de mencionar el hecho de que podra estar obviando, quizs sin quererlo, algunos detalles importantes, mas me he esforzado para que esto no sea as. Es bueno dejar en claro que como este concepto es nativo del sistema operativo UNIX algunos conceptos o notaciones podran ser pocos claros, pero he intentado utilizar un lenguaje ms conciliador. Espero que al termino de la lectura, muchas de las interrogantes hayan sido despejadas y que sirva como base para un camino ms profundo de investigacin a este tema.

Dnde nos Movemos? Lo primero para entrar en materia sera definir cul es nuestro campo de accin, o sea, el medio ambiente en el cual desarrollaremos nuestro trabajo y en el que programaremos lo que haya que codificar para culminar nuestras tareas. Inevitablemente a la hora de entrar en materia de Sockets tendremos que caer en lo que a eleccin de un protocolo de red se refiere, pues nuestro objetivo, aunque no sea en un 100%, estar orientado a la transmisin de informacin desde un lugar a otro. Sin desmerecimiento de aquellos que quisiesen trabajar de un computador a otro en forma local, pero con esto perderamos mucho de lo que queremos aprender o llegar a entender. Sin querer tratar este trabajo como un compendio de Redes se hace justificable hacer mencin a algunos conceptos bsicos en las transmisiones de informacin, as que esta primera parte ser dedicada a esto. I. Parte Conceptos Bsicos de Redes Protocolo de Comunicaciones Para que dos o ms ordenadores puedan conectarse a travs de una red y ser capaces de intercambiar datos de una forma ordenada, deben seguir un protocolo de comunicaciones que sea aceptado por todos ellos. El protocolo define las reglas que se deben seguir en la comunicacin, por ejemplo, ensear a los nios a decir por favor y gracias es una forma de indicarles un protocolo de educacin, y si alguna vez se olvidan de dar las gracias por algo, seguro que reciben una reprimenda de sus mayores. Hay muchos protocolos disponibles para ser utilizados; por ejemplo, el protocolo HTTP define como se van a comunicar los servidores y navegadores Web y el protocolo SMTP define la forma de transferencia del correo electrnico. Estos protocolos, son protocolos de aplicacin que actan al nivel de superficie, pero tambin hay otros protocolos de bajo nivel que actan por debajo del nivel de aplicacin. Capas de Red Las redes estn separadas lgicamente en capas, o niveles, o layers; desde el nivel de aplicacin en la parte ms alta hasta el nivel fsico en la parte ms baja. Los detalles tcnicos de la divisin en capas o niveles de la red se escapan de este trabajo. La nica capa interesante para el usuario y el programador es el Nivel de Aplicacin, que es el que se encarga de tomar los datos en una mquina desde esta capa y soltarlos en la otra mquina en esta misma capa, los pasos intermedios y los saltos de capas que se hayan producido por el camino estn ocultos.

La figura siguiente muestra la correlacin existente entre el modelo terico de capas o niveles de red propuestos por la Organizacin de Estndares Internacional (ISO, International Standards Organisation) y el modelo empleado por las redes TCP/IP. Cuando se presenta un problema de tamao considerable, la solucin ms ptima comienza por dividirlo en pequeas secciones, para posteriormente proceder a solventar cada una de ellas independientemente. Pues el mismo principio de divide y vencers es el que se sigue a la hora de disear redes, es decir, separar en un buen nmero de niveles el hecho de la transmisin de un sistema a otro. Como referencia, la ISO, cre un modelo de interconexin de sistemas abiertos, conocido como OSI. Ese modelo divide en siete capas el proceso de transmisin de informacin entre equipos informticos, desde el hardware fsico, hasta las aplicaciones de red que maneja el usuario. Estas capas son las que se pueden ver en la figura siguiente: fsica, de enlace de datos, de red, de transporte, de sesin, de presentacin y, por ltimo, de aplicacin. Cada nuevo protocolo de red que se define se suele asociar a uno (o a varios) niveles del estndar OSI. Internet dispone de un modelo ms sencillo; no define nada en cuanto al aspecto fsico de los enlaces, o a la topologa o clase de red de sus subredes y, por lo tanto, dentro del modelo OSI, slo existe una correlacin con los niveles superiores. Las aplicaciones que trabajan a un cierto nivel o capa, slo se comunican con sus iguales en los sistemas remotos, es decir, a nivel de aplicacin; un navegador slo se entiende con un servidor Web, sin importarle para nada cmo le llega la informacin. Este mismo principio es el que se emplea para el resto de las capas. Para ilustrar este concepto de capas o niveles, puede resultar explicativo ver qu sucede cuando se solicita una pgina Web. En este caso, el navegador realiza una peticin HTTP, peticin que se incluye en un paquete TCP, que a su vez es encapsulado y fragmentado en uno o varios datagramas IP, que es la unidad de datos a nivel de red. Dichos datagramas son de nuevo encapsulados en unidades de datos PPP, o frames, que se envan al proveedor de Internet a travs del mdem, que transforma esas unidades digitales de datos en seales acsticas de acuerdo a una determinada norma, V.34bis o V.90, por ejemplo. El proveedor de Internet ensamblar los paquetes PPP para convertirlos de nuevo en datagramas IP, que son llevados a su destino, donde sern decodificados en sentido inverso al realizado en el equipo originador de la peticin, hasta que alcancen el nivel de aplicacin, que supone el servidor web. De todo esto, se deben sacar tres ideas fundamentales. En primer lugar, que TCP/IP opera slo en los niveles superiores de red, resultndole indiferente el conjunto de protocolos que se entienden con los adaptadores de red Token Ring, Ethernet, ATM, etc., que se encuentren por debajo. En segundo lugar, que IP es un protocolo de datagramas que proporciona una interfaz estndar a protocolos superiores. Y, en tercer lugar, que dentro de estos protocolos superiores se incluyen TCP y UDP, los cuales ofrecen prestaciones adicionales que ciertas aplicaciones de red necesitan. Cliente y Servidor Este es un trmino comnmente aplicado a la arquitectura del software en el cual las funciones de procesamiento estn segmentadas en colecciones independientes de servicios y peticiones en una nica mquina o divididas en varias mquinas. Uno o ms procesos del Servidor otorgan los servicios a otros clientes en el mismo o a travs de mltiples plataformas de trabajo. Un Servidor encapsula completamente sus procesos y presenta una interfaz bien definida para los clientes. IP, Internet Protocol Es el protocolo que se utiliza por debajo del Nivel de Aplicacin para traspasar datos entre cliente y servidor. El lector no necesita ms que saber de su existencia; no obstante, indicar que es un protocolo de red encargado de mover datos en forma de paquetes entre un origen y un destino y que, como bien indica su nombre, es el protocolo que normalmente se utiliza en Internet. IP es un protocolo simple, fcilmente implementable, de pequeas unidades de datos o datagramas, que proporciona un interfaz estndar a partir del cual el resto de los protocolos y servicios pueden ser construidos, 4

sin tener que preocuparse de las diferencias que existan entre las distintas subredes por las cuales circulen los datos. Todo dispositivo conectado a Internet o a cualquier red basada en TCP/IP, posee al menos una direccin IP, un identificador que define unvocamente al dispositivo que lo tiene asignado en la red. Un datagrama IP se encuentra dividido en dos partes: cabecera y datos. Dentro de la cabecera se encuentran, entre otros campos, la direccin IP del equipo origen y la del destino, el tamao y un nmero de orden. IP opera entre un sistema local conectado a Internet y su router o encaminador ms prximo, as como entre los distintos encaminadores que forman la red. Cuando un datagrama llega a un encaminador, ste determina, a partir de su direccin IP de destino, hacia cul de sus conexiones de salida ha de dirigir el datagrama que acaba de recibir. Por desgracia, en cuanto al transporte, IP provee un servicio que intenta entregar los datos al equipo destino, pero no puede garantizar la integridad, e incluso la recepcin de esos datos. Por ello, la mayora de las aplicaciones hacen uso de un protocolo de ms alto nivel que ofrezca el grado de fiabilidad necesario. Cada datagrama IP es independiente del resto, por lo que cada uno de ellos es llevado a su destino por separado. La longitud del datagrama es variable, pudiendo almacenar hasta 65 Kbytes de datos; si el paquete de datos (TCP o UDP) sobrepasa ese lmite, o el tamao de la unidad de datos de la red que se encuentra por debajo es ms pequeo que el datagrama IP, el mismo protocolo IP lo fragmenta, asignndole un nmero de orden, y distribuye empleando el nmero de datagramas que sea necesario. TCP, Transmission Control Protocol Hay veces en que resulta de vital importancia tener la seguridad de que todos los paquetes que constituyen un mensaje llegan a su destino y en el orden correcto para la recomposicin del mensaje original por parte del destinatario. El protocolo TCP se incorpor al protocolo IP para proporcionar a ste la posibilidad de dar reconocimiento de la recepcin de paquetes y poder pedir la retransmisin de los paquetes que hubiesen llegado mal o se hubiesen perdido. Adems, TCP hace posible que todos los paquetes lleguen al destinatario, juntos y en el mismo orden en que fueron enviados. Por lo tanto, es habitual la utilizacin de los dos acrnimos juntos, TCP/IP, ya que los dos protocolos constituyen un mtodo ms fiable de encapsular un mensaje en paquetes, de enviar los paquetes a un destinatario, y de reconstruir el mensaje original a partir de los paquetes recibidos. TCP, en resumen, ofrece un servicio de transporte de datos fiable, que garantiza la integridad y entrega de los datos entre dos procesos o aplicaciones de mquinas remotas. Es un protocolo orientado a la conexin, es decir, funciona ms o menos como una llamada de telfono. En primer lugar, el equipo local solicita al remoto el establecimiento de un canal de comunicacin; y solamente cuando ese canal ha sido creado, y ambas mquinas estn preparadas para la transmisin, empieza la transferencia de datos real. UDP, User Datagram Protocol Hay veces en que no resulta tan importante que lleguen todos los mensajes a un destinatario, o que lleguen en el orden en que se han enviado; no se quiere incurrir en una sobrecarga del sistema o en la introduccin de retrasos por causa de cumplir esas garantas. Por ejemplo, si un ordenador est enviando la fecha y la hora a otro ordenador cada 100 milisegundos para que la presente en un reloj digital, es preferible que cada paquete llegue lo ms rpidamente posible, incluso aunque ello signifique la prdida de algunos de los paquetes. El protocolo UDP est diseado para soportar este tipo de operaciones. UDP es, por tanto, un protocolo menos fiable que el TCP, ya que no garantiza que una serie de paquetes lleguen en el orden correcto, e incluso no garantiza que todos esos paquetes lleguen a su destino. Los procesos que hagan uso de UDP han de 5

implementar, si es necesario, sus propias rutinas de verificacin de envo y sincronizacin. Como programador, el lector tiene en sus manos la eleccin del protocolo que va a utilizar en sus comunicaciones, en funcin de las caractersticas de velocidad y seguridad que requiera la comunicacin que desea establecer.

Direccin IP La verdad es que no se necesita saber mucho sobre el protocolo IP para poder utilizarlo, pero s que es necesario conocer el esquema de direccionamiento que utiliza este protocolo. Cada ordenador conectado a una red TCP/IP dispone de una direccin IP nica de 4 bytes (32 bits), en donde, segn la clase de red que se tenga y la mscara, parte de los 4 bytes representan a la red, parte a la subred (donde proceda) y parte al dispositivo final o nodo especfico de la red. La figura siguiente muestra la representacin de los distintos nmeros de una direccin IP de un nodo perteneciente a una subred de clase B (mscara 255.255.0.0). Con 32 bits se puede definir una gran cantidad de direcciones nicas, pero la forma en que se asignaban estas direcciones estaba un poco descontrolada, por lo que hay muchas de esas direcciones que a pesar de estar asignadas no se estn utilizando. Por razones administrativas, en los primeros tiempos del desarrollo del protocolo IP, se establecieron cinco rangos de direcciones, dentro del rango total de 32 bits de direcciones IP disponibles, denominando a esos subrangos, clases. Cuando una determinada organizacin requiere conectarse a Internet, solicita una clase, de acuerdo al nmero de nodos que precise tener conectados a la Red. La administracin referente a la cesin de rangos la efecta InterNIC (Internet Network Information Center), aunque existen autoridades que, segn las zonas, gestionan dominios locales; por ejemplo, el dominio correspondiente a Espaa lo gestiona Red Iris. Los subrangos se definen en orden ascendente de direcciones IP, por lo cual, a partir de una direccin IP es fcil averiguar el tipo de clase de Internet con la que se ha conectado. El tipo de clase bajo la que se encuentra una direccin IP concreta viene determinado por el valor del primer byte de los cuatro que la componen o, lo que es igual, el primer nmero que aparece en la direccin IP. Las clases toman nombre de la A a la E, aunque las ms conocidas son las A, B y C. En Internet, las redes de clase A son las comienzan con un nmero entre el 1 y el 126, que permiten otorgar el mayor nmero de direcciones IP (16,7 millones), por lo que se asignan a grandes instituciones educativas o gubernamentales. Las clases B (65536 direcciones por clase), suelen concederse a grandes empresas o corporaciones y, en general, a cualquier organizacin que precise un importante nmero de nodos. Las redes de clase C (256 direcciones) son las ms comunes y habitualmente se asignan sin demasiados problemas a cualquier empresa u organizacin que lo solicite. La clase D se reserva a la transmisin de mensajes de difusin mltiple (multicast), mientras que la clase E es la destinada a investigacin y desarrollo. La tabla siguiente resume estos datos:

Todo lo dicho antes solamente implica a la asignacin de direcciones dentro de Internet. Si se disea una red TCP/IP que no vaya a estar conectada a la Red, se puede hacer uso de cualquier conjunto de direcciones IP. Solamente existen cuatro limitaciones, intrnsecas al protocolo, a la hora de escoger direcciones IP, pero que reducen en cierta medida el nmero de nodos disponibles por clase que se indicaban en la tabla anterior. La primera es que no se pueden asignar direcciones que comiencen por 0; dichas direcciones hacen referencia a nodos dentro de la red actual. La segunda es que la red 127 se reserva para los procesos de resolucin de problemas y diagnosis de la red; de especial inters resulta la direccin 127.0.0.1, bucle interno (loopback) de la estacin de trabajo local. La tercera consiste en que las direcciones IP de nodos no pueden terminar en 0, o en cualquier otro valor base del rango de una subred; porque es as como concluyen las redes. Y, por ltimo, cuando se asignan direcciones a nodos, no se pueden emplear el valor 255, o cualquier otro valor final del rango de una subred. Este valor se utiliza para enviar mensajes a todos los elementos de una red (broadcast); por ejemplo, si se enva un mensaje a la direccin 192.168.37.255, se estara enviando en realidad a todos los 6

nodos de la red de clase C 192.168.37.xx. Ahora bien, si se quiere que una red local tenga acceso exterior, hay una serie de restricciones adicionales, por lo que hay una serie de direcciones reservadas que, a fin de que pudiesen ser usadas en la confeccin de redes locales, fueron excluidas de Internet. Estas direcciones se muestran en la siguiente tabla. Actualmente, se intenta expandir el nmero de direcciones nicas a un nmero mucho mayor, utilizando 128 bits. E.R. Harold, en su libro Java Network Programming, dice que el nmero de direcciones nicas que se podra alcanzar representando las direcciones con 128 bits es 1.6043703E32. La verdad es que las direcciones indicadas de esta forma son difciles de recordar, as que lo que se hace es convertir el valor de los cuatro bytes en un nmero decimal y separarlos por puntos, de forma que sea mucho ms sencillo el recordarlos; por ejemplo, la direccin nica asignada a java.sun.com es 204.160.241.98. Dominios Y ahora surge la pregunta de qu es lo que significa java.sun.com. Como a pesar de que la direccin nica asignada a un ordenador se indique con cuatro cifras pequeas, resulta muy difcil recordar las direcciones de varias mquinas a la vez; muchas de estas direcciones se han hecho corresponder con un nombre, o dominio, constituido por una cadena de caracteres, que es mucho ms fcil de recordar para los humanos. As, el dominio para la direccin IP 204.160.241.98 es java.sun.com. El Sistema de Nombres de Dominio (DNS, Domain Name System) fue desarrollado para realizar la conversin entre los dominios y las direcciones IP. De este modo, cuando el lector entra en Internet a travs de su navegador e intenta conectarse con un dominio determinado, el navegador se comunica en primer lugar con un servidor DNS para conocer la direccin IP numrica correspondiente a ese dominio. Esta direccin numrica IP, y no el nombre del dominio, es la que va encapsulada en los paquetes y es la que utiliza el protocolo Internet para enrutar paquetes desde el ordenador del lector hasta su destino. Puertos y Servicios Un servicio es una facilidad que proporciona el sistema, y cada uno de estos servicios est asociado a un puerto. Un puerto es una direccin numrica a travs de la cual se procesa el servicio, es decir, no son puertos fsicos semejantes al puerto paralelo para conectar la impresora en la parte trasera del ordenador, sino que son direcciones lgicas proporcionadas por el sistema operativo para poder responder. Sobre un sistema Unix, por ejemplo, los servicios que proporciona ese sistema y los puertos asociados por los cuales responde a cada uno de esos servicios, se indican en el fichero /etc/services, y algunos de ellos son: daytime 13/udp ftp 21/tcp telnet 23/tcp telnet smtp 25/tcp mail http 80/tcp La primera columna indica el nombre del servicio. La segunda columna indica el puerto y el protocolo que est asociado al servicio. La tercera columna es un alias del servicio; por ejemplo, el servicio smtp, tambin conocido como mail, es la implementacin del servicio de correo electrnico.

Las comunicaciones de informacin relacionada con Web tienen lugar a travs del puerto 80 mediante protocolo TCP. Tericamente hay 65535 puertos disponibles, aunque los puertos del 1 al 1023 estn reservados al uso de servicios estndar proporcionados por el sistema, quedando el resto libre para utilizacin por las aplicaciones de usuario. De no existir los puertos, solamente se podra ofrecer un servicio por mquina. Ntese que el protocolo IP no sabe nada al respecto de los nmeros de puerto, al igual que TCP y UDP no se preocupan en absoluto por las direcciones IP. Se puede decir que IP pone en contacto las mquinas, TCP y UDP establecen un canal de comunicacin entre determinados procesos que se ejecutan en tales equipos y, los nmeros de puerto se pueden entender como nmeros de oficinas dentro de un gran edificio. El edificio (equipo), tendr una nica direccin IP, pero dentro de l, cada tipo de negocio, en este caso HTTP, FTP, etc., dispone de una oficina individual. Cortafuegos Un cortafuegos(Firewall) es el nombre que se da a un equipo y su software asociado que permite aislar la red interna de una empresa del resto de Internet. Normalmente se utiliza para restringir el grado de acceso a los ordenadores de la red interna de una empresa desde Internet, por razones de seguridad o cualquier otra. Servidores Proxy Un servidor proxy acta como interfaz entre los ordenadores de la red interna de una empresa e Internet. Frecuentemente, el servidor proxy tiene posibilidad de ir almacenando un cierto nmero de pginas web temporalmente en cach, para un acceso ms rpido. Por ejemplo, si diez personas dentro de la empresa intentan conectarse a un mismo servidor Internet y descargar la misma pgina en un perodo corto de tiempo, esa pgina puede ser almacenada por el servidor proxy la primera vez que se accede a ella y proporcionarla l, sin necesidad de acceder a Internet, a las otras nueve personas que la han solicitado. Esto reduce en gran medida el tiempo de espera por la descarga de la pgina y el trfico, tanto dentro como fuera de la empresa, aunque a veces puede tambin hacer que la informacin de la pgina se quede sin actualizar, al no descargarse de su sitio original. URL, Uniform Resource Locator Una URL , o direccin, es en realidad un puntero a un determinado recurso de un determinado sitio de Internet. Al especificar una URL, se est indicando: El protocolo utilizado para acceder al servidor (http, por ejemplo) El nombre del servidor El puerto de conexin (opcional) El camino (directorio) El nombre de un fichero determinado en el servidor (opcional a veces) Un punto de referencia dentro del fichero (opcional) La sintaxis general, resumiendo pues, para una direccin URL, sera: protocolo://nombre_servidor[:puerto]/directorio/fichero#referencia El puerto es opcional y normalmente no es necesario especificarlo si se est accediendo a un servidor que proporcione sus servicios a travs de los puertos estndar; tanto el navegador como cualquier otra herramienta que se utilice en la conexin conocen perfectamente los puertos por los cuales se proporciona cada uno de los servicios e intentan conectarse directamente a ellos por defecto.

Concluida la primera parte en la que slo se pretenda presentar una variedad de conceptos de manejo imprescindible en lo que a redes y procesos de comunicacin se refiere ya podremos pasar a la siguiente etapa que es el trabajo en s ahora, Porqu es necesario que rayemos la cancha?. Simple, este concepto proviene de UNIX, y pese a que se han implementado diferentes tipos de Sockets( o formatos descriptivos que emulan este comportamiento, tales como Winsocket para Windows, SSL en Netscape) en los ms diversos medioambientes de trabajo, profundizaremos su estudio a este Sistema Operativo y, por lo tanto, a su protocolo de transmisin y se hace muy necesario que cuando hablemos de estos trminos no tengamos vacos en nuestro acervo tecnolgico. II Parte. UNIX y los Sockets Sin duda habrs escuchado muchas veces el trmino Socket, pues bien, sin definirlo a la perfeccin todava los Sockets son una forma de hablar con otros archivos usando los descriptores de archivos standard de UNIX. Lo ms probable es que tambin hayas escuchado muchas veces la profundizacin de que en UNIX todo es un archivo, esto se explica por el hecho de que cuando UNIX hace cualquier tipo de ordenamiento de I/O, lo realiza mediante la lectura o escritura de un descriptor de archivo. Un descriptor de archivo es simplemente un entero asociado con el archivo abierto, pero he aqu el truco, ese archivo puede ser una conexin a redes, un FIFO, un Pipe, una terminal o cualquier otra cosa. Es debido a esto que se ha acuado la frase ya mencionada. Una vez comprendido esto vamos a la captura de este descriptor, Cmo lo hacemos?, La respuesta es la llamada Socket(), la cual te regresa el descriptor y entonces puedes comunicarte a travs de l usando las llamadas especializadas sendto() y recvfrom(). Ahora Porqu no usar las llamadas read() y write()normales para comunicarme a travs del Socket? Simple, porque aunque puedes, perfectamente hacerlo, no obtendrs el mximo manejo que te ofrecen sendto() y recvfrom(), para la transmisin de datos. Qu son los Sockets? Ok, entrando en lo que a materia de trabajo se refiere, los Sockets tienen la ms amplia y variada cantidad de definiciones que he visto, no he logrado encontrar un par de ellas en la red que compartan el mismo cuerpo, aunque si la misma filosofa en su enunciado, aunque todas ellas tienen un punto en comn y es, que se les considera el componente sin el cual la transmisin de datos no sera posible. Pues bien veamos algunas definiciones antes de dar la nuestra: Un Socket es un punto de comunicacin, que se comunica con otro Socket para enviarle mensajes. Son bidireccionales, los hay de varios tipos y nos permiten comunicarnos con un proceso que est en otro computador (Linux Actual, ao 1, nmero 9) Los Sockets son puntos finales de enlaces de comunicaciones entre procesos. Los procesos los tratan como descriptores de ficheros, de forma que se pueden intercambiar datos con otros procesos transmitiendo y recibiendo a travs de Sockets. El tipo de Sockets describe la forma en la que se transfiere informacin a travs de ese Socket. (Tutorial de Java, Agustn Froufe, http://members.es.tripod.de/froufe/index.html) Un Socket es una entidad de software que provee el bloque de construccin bsica para las comunicaciones interprocesos. Los Sockets permiten a los procesos reunirse en un nombre de espacio UNIX a travs del cual producen un intercambio de informacin. Un Socket es el punto final de proceso de comunicacin entre procesos. Para. Direcciones IPX un par de nombres bien definidos identifican el par de Sockets entre medios de comunicacin.(Esta la extraje de una pgina de la red, pero no tena mayor info del autor, ni de dnde provena). Los Sockets son como los hoyos de los gusanos en la cienciaficcin, cuando las cosas entran por una parte, deberan salir por otra. Diferentes tipos de Sockets tienen diferentes propiedades.(Grupo de noticias de UNIX, sacado de un FAQ, http://www.ibrado.com/sockfaq/) 9

Las definiciones demuestran que no me haba desmandado en lo absoluto a la hora de describirles sobre el poco consenso que hay cuando de unificar criterios se trata. Intentando generar una definicin propia podra decir que los Sockets son un concepto abstracto que define el punto final de una transmisin entre dos computadoras, por lo que resulta bidireccional. Cada uno de los Sockets tiene una nica direccin que se describe genricamente por el comando sockaddr de 16 bytes en la estructura de programacin en C. Este concepto se introdujo en UNIX Berkeley, si quisisemos describirlo mediante un ejemplo consideremos lo siguiente: Un Socket resultara como un adaptador virtual entre un programa y un protocolo de red. Si tuvisemos un servidor FTP en lnea, un Socket se creara por el servidor del programa FTP, su trabajo consiste en escuchar en el puerto 21 del TCP, y si el IP pasa algn paquete, el Socket lo pasar al servidor FTP. Aunque no he sido muy fino en mis palabras, creo que el ejemplo ilustra bastante bien, lo que he intentado explicar. Tipos de Sockets Existen variados tipos de Sockets como intentar explicar de ahora en adelante, pero generalizando, los hay como direcciones DARPA de Internet(Internet Sockets), nombre de camino en un nodo local(UNIX Sockets), direcciones CCITT X25(X 25 Sockets estos los puedes ignorar sin ningn complejo) y muchos otros todo esto depende del tipo de ambiente UNIX que corras. Siendo ms tcnicos diremos que Un Socket tiene una categora y uno o ms procesos asociados. Los Sockets son categorizados por las propiedades de comunicacin que le son visibles al programador. Usualmente la categora del Socket esta asociada al protocolo en particular que lo soporta y los procesos, por lo general, comunican Sockets del mismo tipo. Debido a estas caractersticas podremos ponernos en contacto con cualquier punto de comunicacin de cualquier computador conectado a la red. Concluyamos algunos puntos: Hasta aqu ha quedado claro que si quiero transmitir informacin deber crear mi Socket para poder enviarla, luego el receptor tambin deber crear su Socket para recepcionarla. Los datos que identificarn unvocamente a los puntos de transmisin que he sealado anteriormente son los siguientes: La direccin IP del computador en donde reside el programa que est usando este punto de conexin. Un nmero de puerto. El puerto en un nmero entero de 16 bits, cuyo uso es el de permitir que en un ordenador puedan existir 65536 puntos posibles de comunicacin para cada tipo de Socket. Esto es suficiente para que no suponga un lmite, en la prctica, al nmero de puertos de comunicacin diferentes que puede haber al mismo tiempo en un ordenador. El tipo de Socket, dato que no reside en la informacin de direccionamiento, ya que es algo implcito al Socket. Si usamos un Socket de un tipo, ste slo se comunicar con otro del mismo tipo. Para referirnos a un Socket, usamos una direccin de Socket. Las direcciones de Sockets son diferentes segn la familia. Llevan todos un primer parmetro que identifica la familia del Socket y, luego, segn sta, los datos correspondientes.

Generalmente disponemos de tres tipos de Sockets para Internet y estos son:

10

Stream Socket SPX Datagram Socket IPX Raw Socket (No trabajar con estos aunque har alguna referencia de ellos) Con esto no quiero enfatizarles que existen slo estos, cmo les he explicado existen muchos ms, pero no quiero hacer eterno este trabajo. Los Raw Sockets dan acceso directo a la capa de software de red subyacente o a protocolos de ms bajo nivel. Se utilizan sobre todo para la depuracin del cdigo de los protocolos. Los Raw Sockets proporcionan acceso al Internet Control Message Protocol, ICMP, y se utiliza para comunicarse entre varias entidades IP. Stream Sockets y Datagram Sockets Comenzaremos haciendo un comparendo entre estos dos tipos de Sockets para que puedan quedar ms claras las diferencias. Los Stream Sockets son los ms confiables y representan una forma del flujo de comunicacin bidireccional. Si envas dos tems de informacin en el orden 1 2, se recibir la informacin en el lado opuesto en el orden 1 2. Por conclusin diremos que la comunicacin se produjo libre de errores que es lo que esperamos que siempre ocurra. Este uso est muy arraigado en cualquier aplicacin de Internet, ya que todos los caracteres que se tipeen necesitan llegar en ese mismo orden a su destino. Los navegadores de Internet usan el protocolo HTTP, con los Stream Sockets para poder obtener las pginas. Si te conectas a un sitio mediante el puerto 80 y tipeas Get nombre de pgina el html de la pgina se mostrar ante ti. Para obtener la calidad necesaria de alto nivel que esta transmisin de datos requiere, utilizan el famoso protocolo TCP(Transmission Control Protocol) o Protocolo de Control de Transmisin, es este TCP el que se asegura que los datos lleguen secuencialmente y libres de error, pero de darse el caso de que no se pudiera enviar la informacin quien haya hecho el intento recibir la notificacin correspondiente. Otra caracterstica radica en que no hay lmites en la extensin de los registros. No esta de ms agregar que este protocolo es la media mitad del IP(Internet Protocol) o Protocolo de Internet, mas el IP se maneja con el enrutamiento en Internet solamente. Bien, que hay de los Datagram Sockets. No tienen tan buena fama como sus pares Stream y esto por que el protocolo usado por estos es el UDP(User Datagram Protocol) o Protocolo de Usuario de Datagramas. Este mtodo consiste en enviar paquetes de datos a un destino determinado. Cada paquete que enviemos ha de llevar la direccin de destino, y ser guiado por la red independientemente. Estos paquetes con direccin incluida son lo que llamamos datagramas. Los datagramas tienen una longitud limitada, por lo que los datos a enviar no pueden traspasar esa longitud. Otros detalles provienen del hecho que se transite por una red de rea extensa, o sea que al transitar por estas grandes extensiones se puede llegar a producir los siguientes acontecimientos:

Prdida de Paquetes : En el nivel de red, en los nodos de enrutamiento se puede perder paquetes debido a la congestin, problemas en la transmisin, etc. Orden de los Paquetes : Debido a la distancia los paquetes deben atravesar por varios nodos para llegar a su destino. En estos nodos, los algoritmos suelen no ser estticos y esto se traduce en que un paquete puede seguir diferentes caminos en un mismo instante, debido a que el nodo lo decide as. Este cambio de rutas lo decide el nodo al posiblemente encontrar problemas de congestin por la 11

sobrecarga en las lneas. Como conclusin tenemos que dos paquetes que fueron enviados pueden llegar desordenados al haber seguido rutas distintas. Para terminar agregar que este tipo de conexin es conocido tambin como Connectionless Sockets o Sockets sin Conexin, debido principalmente a que no se necesita tener una conexin abierta permanentemente, slo se crea el paquete se le dice al IP donde tiene que llegar y se enva. Figura Sockets de Datagramas Transmisin de Datagramas En este punto se puede entrar en la duda de si no hay seguridad en el envo de los datagramas, Para qu utilizar este mtodo? Bueno, esto se subsana de la siguiente manera, cada tipo tiene su propio protocolo en la parte ms alta del UDP. Por ejemplo, el protocolo TFTP dice que por cada paquete que lleve el sent(), el recipiente debe enviar de vuelta un paquete en respuesta que diga lo tengo (un paquete ACK). Si quien enva no obtiene respuesta, en digamos 5 segundos, el paquete ser retransmitido hasta obtener la seal de ACK este procedimiento de reconocimiento es muy importante durante la implementacin de las aplicaciones SOCK_DGRAM. En la figura siguiente se ejemplifica mediante un dibujo lo que acabamos de explicar, que es la transmisin segura de Datagramas con la espera de la respuesta de la llegada del datagrama en forma satisfactoria. Lo sabemos por: ACK (Acknowledge) : Recibido. NACK(Not Acknowledge) : No Recibido. EOT (End of Transmission) : Fin de Transmisin.

Figura de una Transmisin Segura de Datagramas Datagrama 1 Perdido Datagrama 2 Perdido Datagrama 3 Los datagramas 1, 2 y 3 llevan los mismos datos, pero diferente informacin de control. Datagrama respuesta lleva el asentimiento sobre si se ha recibido o no. Para transmitir el dato con seguridad, enviamos un datagrama. Si luego de un tiempo no nos llega el asentimiento lo reenviamos. As hasta recibir el asentimiento o demos el destino por inalcanzable luego de varios intentos. Cmo Creo un Socket?

12

Bien, hemos llegado a la sustancia misma del trabajo y desde aqu en adelante las cosas pueden que se compliquen un poco as que trataremos de hacer lo que se requiere con la tranquilidad y claridad necesarias. La creacin bsica de un Socket requiere de dos pasos: Obtener el descriptor del Socket. La direccin del Socket para la correspondiente parte del envo de la informacin. Obtencin del Descriptor(Paso1) #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);

Aqu especificaremos lo siguiente: Domain(Dominio) : Es la familia de la cual proviene nuestro Socket, para las comunicaciones en Redes usaremos AF_INET. Pero puede ser AF_UNIX, o AF_OSI, etc. Type(Tipo) : Tipo de Socket usado. Nos permite diferenciar la situacin de uso de un SOCK_STREAM(orientado a conexin), de SOCK_DGRAM(para datagramas) o SOCK_RAW (nivel IP). Protocol(Protocolo) : Generalmente, implementaremos uno por cada tipo de Socket. Siempre pondremos un 0, que dice que elegiremos el protocolo por defecto para el tipo y dominio de Socket elegido. Con esto podremos obtener el descriptor del Socket, que ser un entero. En caso de fracasar nuestro intento recibiremos un 1. Un ejemplo de una llamada tpica a un Socket(Tipo Datagramas): Int sd; if ((sd = socket(AF_INET, SOCK_DGRAM, 0) < 0) { perror("socket"); exit(1);} Direccin del Socket(Paso2) Ya obtenido el Socket necesitamos poder usarlo para comunicarnos, para esto debe corresponderse con una direccin Socket. La estructura que sigue permite almacenar la direccin Socket como se usa en el dominio AF_INET: struct in_addr { u_long s_addr;

13

}; struct sockaddr_in { u_short sin_family; /*identifica el protocolo; en general AF_INET */ u_short sin_port; /*numero de puerto. 0 deja que el kernel elija*/

struct in_addr sin_addr; /*la direccin IP. Con INADDR_ANY nos deja la opcin de obtener el que queramos dentro del Host en que ejecutamos*/ char sin_zero[8];}; /*Sin usos, siempre cero */ Para poder usar la parte del programa anterior necesitaras agregar: #include <netinet/in.h> Hemos ahora de unirlo, esto se hace mediante la funcin Bind #include <sys/types.h> #include <sys/socket.h> int bind(int sd, struct sockaddr *addr, int addrlen) Donde tenemos que: sd: Es el descriptor del archivo del Socket local, que se cre mediante la funcin Socket. addr: Apunta a la direccin del protocolo de este Socket. Usualmente es INADDR_ANY .El puerto es 0 para solicitar al kernel que entregue un puerto. addrlen: Longitud en bytes de una addr. Regresa un entero, el cdigo es (0 Exitoso, 1 Falla) Este comando Bind, es usado para especificarle al Socket el nmero del puerto donde esperar por los mensajes. He aqu una tpica llamada a este comando: struct sockaddr_in name; bzero((char *) &name, sizeof(name)); /*longitudes*/ name.sin_family = AF_INET; /*usa dominio Internet*/ name.sin_port = htons(0); /*pide al kernel que le otorgue un puerto*/ name.sin_addr.s_addr = htonl(INADDR_ANY); /*usa todos los IPs del host*/ if (bind(sd, (struct sockaddr *)&name, sizeof(name)) < 0) { perror("bind"); 14

exit(1);} Una llamada Bind es opcional por el lado del Cliente, pero necesaria por el lado Servidor.

Quisiera llamar la atencin a ciertos comandos puestos en la estructura anterior que quizs no les hayan quedado muy claros, as que explicaremos las razones del uso de las llamadas htons y htonl. Los nmeros en mquinas diferentes pueden ser representados en forma diferente. Entonces necesitamos asegurarnos sobre la correcta presentacin en el medio que trabajemos. Para eso transformamos mediante funciones desde el Host a un formato de Redes antes de transmitir(htons para enteros de tipo short, y htonl para enteros de tipo long), y desde la Red a un formato del Host despus de la recepcin(ntohs para enteros de tipo short, y ntohl para enteros de tipo long). La funcin bzero est fuera de la longitud especificada para un buffer. Es de un grupo de funciones para manejarse con arreglos de bytes. bcopy copia un nmero especificado de bytes desde un buffer fuente a uno objetivo. Bcmp Compara un nmero especificado de bytes de dos buffers. Una ltima aclaracin aqu es que aunque t le dejes la tarea de la eleccin del puerto al comando bind, o quieras elegirla por ti mismo esta deber estar encima del 1024 ya que esos ya estn reservados, pero no olvides que tienes hasta 65535 para elegir(siempre y cuando no estn siendo ocupados por otros procesos). Opciones de Sockets y Trabajo con Datagramas Bien, quiero empezar a trabajar con mi famoso Socket, o sea, requiero enviar datos, pero podra encontrarme con la novedad de que este se encuentre demasiado cargado o, lisa y llanamente, no sea capaz de contener mi mensaje. Podra suceder que al querer leer un dato no tenga ninguno disponible en ese preciso momento. Lo que, inevitablemente, ocurrira es que me quedara bloqueado y esperando que la operacin se pudiese llevar a cabo, si no deseo esperar tengo la opcin de usar la funcin fcntl para poder cambiar el modo de funcionamiento del Socket. Lo que debera hacer es lo siguiente: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); Recopilando, entonces, este comando fcntl puede ser usada para especificar que un proceso de grupo reciba una seal SIGURG cuando los datos arrojen una seal fuera del ancho de banda. Lo que implementamos fue tambin que fuera capaz de no bloquear I/O y la notificacin asncrona de eventos de I/O va SIGIO. Esto asegura que al querer usar mi Socket y me quedase bloqueado, este me enviara un mensaje de error EWOULDBLOCK, que significa que no realizar la operacin debido a que se bloqueara.

Para concluir con esta parte, explicaremos lo ltimo concerniente a los datagramas y luego terminaremos con la conexin Cliente /Servidor. Datagramas 15

Para el correcto trabajo aqu como ya explicamos en prrafos anteriores hay que usar las funciones sendto() y recvfrom() Los cuerpos son como siguen: Sendto Int sendto(int s, const void *msg, int len, unsigned int flags, cosnt struct sockaddr *to, int, tolen); S : Descriptor del Socket. Msg : Es el puntero a la zona de memoria con los datos. Len : Representa la longitud de los datos. Flags : Modificadores del modo de operacin. Hay que poner un 0. To : Es el puntero a la direccin de destino. Cuando usamos direcciones AF_INET(struct sockaddr_in) deberemos realizar un cast. Tolen : Es el valor de retorno. Acordarse de que el valor de retorno es el nmero de los bytes que se envi y que tendremos 1 si es que hubo algn error. Recvfrom Int recvfrom(int s, void*buf, int lon, unsigned int flags, struct sockaddr *from, int *lonfrom); S : Es el descriptor del Socket. Buf : Zona de memoria donde queremos almacenar los datos recibidos. Lon : Longitud del mensaje que queremos recibir. Flags :Modificador del modo de operacin. Usaremos un 0 desde el puntero hasta la variable donde queremos almacenar la direccin del origen de los datos. La utilidad de esto radica en que es necesario saberlo cuando queremos responder y necesitamos la direccin para mandar la respuesta.. Si usamos direcciones AF_INET(struct sockaddr_in), realizaremos un cast. Si from vale NULL no se escribir nada en l. Lonfrom : Es desde el puntero a un entero donde se nos escribir la longitud del dato direccin. La llamada sendto sirve para enviar datos. Si el tamao de los datos que queremos enviar es demasiado grande, la funcin nos retornar un error, por lo que la variable errno ser puesta al valor emsgsize. Los errores que se nos indicarn sern errores locales, como el excedernos en el ancho, algn parametro ingresado incorrectamente, etc. Si ocurre un error de comunicaciones, el paquete puede perderse en la red, y eso es algo que nosotros no sabremos. Ahora para tratar de evitar esto es que trataremos de pedir el asentimiento. Si el Socket est demasiado cargado y no tiene espacio para almacenar nuestro mensaje se producir lo que ya comentamos, se bloquear la llamada y ya sabemos lo que hay que hacer para que no se nos bloquee. Para recibir datos usamos la llamada recvfrom. El funcionamiento es anlogo al de sendto y cuando no haya datos se bloquear solo, a no ser que nuestro Socket sea no bloqueante. Cuando haya datos disponibles, lo que 16

es por defecto, dar como resultado todos los datos que tenga hasta el solicitado. O sea, que si hay 400 bytes y hemos solicitado 800 recibiremos los 400. III Parte. Sockets Orientados a Conexin. Los Sockets orientados a conexin se utilizan de modo muy diferente a los Sockets de Datagramas. Obedecen a una arquitectura Cliente/Servidor. Por consiguiente, habr un extremo de la comunicacin que actuar como servidor, en el que se esperarn las peticiones de conexin, y otro extremo que solicitar la realizacin de las comunicaciones desempeando el rol del cliente. Figura Relacin Cliente Servidor El Servidor Muy bien ahora comienzas a querer conectarte a un servidor remoto para comenzar a recibir informacin y poder manejarla. El proceso servidor ha de crear un Socket y enlazar la direccin, algo que me imagino en este punto ya debe resultar ms que obvio, debes sin embargo cambiar el tipo, o sea, ahora debemos poner SOCK_STREAM.

Los pasos para poder hacer lo que se pretende son dos y muy claros: Primero debes escuchar y luego aceptar las conexiones. Ok, el cuerpo para poder realizar estas acciones es el que sigue: Funcin Listen() int listen(int sockfd, int backlog); sockfd : Es el descriptor de archivo Socket usual. Backlog : Es el nmero de conexiones permitidas en la fila entrante. Ahora que significa que estn en cola, pues bien todas las conexiones entrantes van a esperar en esta fila hasta que t aceptes. Ahora Cmo saber el nmero de conexiones entrantes?, Bueno la mayora de los sistemas silenciosamente limita este nmero a cerca de 20, probablemente puedas manejarte mejor con un nmero entre 5 a 10. Lo importante aqu es que cuando alcancemos ese nmero mximo las otras conexiones pendientes sern rechazadas. Posiblemente ya te hayas imaginado que necesitamos realizar la llamada bind() antes de llamar a listen(), pues de lo contrario el Kernel nos tendr escuchando en puertos al azar. Por lo tanto esta debe ser la secuencia que debes tener en mente para no pasarte la vida entera escuchando. socket(); bind(); listen(); /* accept() esta llamada va aqu*/

17

Funcin Accept() Esta llamada es algo extraa y te lo dirn en cada manual que leas, pero tratar de explicarlo lo ms claro posible. Qu sucede si alguien muy a lo lejos intentara una conexin contigo en el puerto en el cual t ests escuchando?. Esta llamada quedar en cola hasta que t aceptes. Ok, t aceptas mediante accept() y este se encarga de confirmar lo que t quieres, aqu se te regresa un nuevo descriptor de archivo Socket, repentinamente tiene que manejar 2 Sockets por el mismo precio. El original que siguen escuchando en tu puerto y el nuevo que esta finalmente listo para un send() y un recv(). Veamos esto en cdigo: La llamada es como sigue: #include <sys/socket.h> int accept(int sockfd, void *addr, int *addrlen); sockfd : Este es el descriptor del Socket que escucha. addr : Ser usualmente un puntero a un struct sockaddr_in. local. Esto es donde la informacin sobre la conexin entrante se almacenar. (Y poder determinar que Host te llama y de qu puerto lo hace).

addrlen : Es un entero que establece el tamao de sizeof(struct sockaddr_in) antes de que la direccin sea pasada a accept().Por lo tanto, la llamada accept no colocar ms que estos bytes dentro de addr. Si colocara menos cambiara el valor de addrlen lo que reflejara que accept() regres un 1 o sea un error. #include <string.h> #include <sys/types.h> #include <sys/socket.h> #define MYPORT 3490 /* Puerto al que se conectarn */ #define BACKLOG 10 /* cuantas conexiones pendientes se mantendrn en cola */ main() { int sockfd, new_fd; /* Escucha en sock_fd, la nueva en new_fd */ struct sockaddr_in my_addr; /* Mi informacin de direccin*/ struct sockaddr_in their_addr; /* Informacin de direccin de quien se conecta*/ int sin_size; sockfd = socket(AF_INET, SOCK_STREAM, 0); /* Checa errores */ my_addr.sin_family = AF_INET; /* orden de bytes del Host*/

18

my_addr.sin_port = htons(MYPORT); /* tipo short, Orden en bytes de la red */ my_addr.sin_addr.s_addr = INADDR_ANY; /* Auto completa con mi IP */ bzero(&(my_addr.sin_zero), 8); /* zero resto de struct*/ /* no hay que olvidar chequeo de errores para estas llamadas*/ bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); listen(sockfd, BACKLOG); sin_size = sizeof(struct sockaddr_in); new_fd = accept(sockfd, &their_addr, &sin_size); Notar que se usa el descriptor socketnew_fd para todos los send() y recv(). Si slo se obtiene una conexin, se puede cerrar close() el sockfd original para prevenir la llegada de nuevas conexiones al mismo puerto, claro si es que esto se desea. Otro aspecto interesante aqu es que como ya se sabe, el nuevo descriptor de Socket tiene las mismas caractersticas que el nuestro(para poder realizar la conexin). Ahora sabemos que a travs de nuestro Socket podemos establecer varias conexiones con distintos orgenes y realizamos las conexiones pertinentes con el descriptor devuelto en cada caso. Esto se puede ejemplificar con los demonios servidores. Cuya misin consiste en estar escuchando en el Socket y aceptar conexiones con accepts. Cuando reciben una peticin, guardan el descriptor del Socket devuelto y hacen un nuevo proceso hijo. Es este hijo quien se encarga de las comunicaciones, y de paso permite al padre seguir esperando nuevas conexiones.

Figura Funcionamiento de un servidor atendiendo varias conexiones en paralelo Creacin de una conexin Situacin en un momento dado 1 Proceso Padre escuchando 34 5 1. Cliente pide conexin. 2. Servidor atiende conexin por 3. Se crea la conexin 4. El servidor hace un hijo y sigue escuchando 5. El hijo hereda la comunicacin del padre y se comunica con el cliente.

19

El Cliente El cliente ha de seguir los pasos de siempre al crear un Socket AF_INET y SOCK_STREAM, y luego enlazarlo a una direccin. En esto debe cumplimentar los datos de la direccin del servidor al que se quiere conectar y pedir establecer la conexin. Esto ltimo se hace con la funcin Connect. Funcin Connect() #include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); sockfd Es el descriptor del socket. serv_addr Es una struct sockaddr que contiene el puerto de destino y la direccin IP. addrlen Establece la longitud de la direccin (struct sockaddr). #include <string.h> #include <sys/types.h> #include <sys/socket.h> #define DEST_IP "132.241.5.10" #define DEST_PORT 23

main() int sockfd; struct sockaddr_in dest_addr; /* Mantendr la direccin de destino*/ sockfd = socket(AF_INET, SOCK_STREAM, 0); /*Chequeo de errores*/ dest_addr.sin_family = AF_INET; /* orden de bytes del host */ dest_addr.sin_port = htons(DEST_PORT); /* tipo short, orden de bytes de la red*/ dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); bzero(&(dest_addr.sin_zero), 8); /* zero el resto de struct */ /* Chequeo de errores para connect()! */ connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));

20

Como ya se sabe si algo falla tendremos de vuelta un 1. Tambin notar que no llamamos a bind(), esto bsicamente por que no nos importa nuestro nmero de puerto local, slo nos interesa hacia dnde vamos. El Kernel elegir un puerto local para nosotros y el sitio al que nos conectemos automticamente obtendr esta informacin. Funciones Close() y Shutdown() Bueno supongo que ya has estado recibiendo y mandando informacin todo el da y ya es hora de terminar esta agotadora jornada. Qu hacemos ahora?. Bueno eso resulta obvio cerramos y apagamos. Lo primero es muy fcil usamos el descriptor de archivo de Unix close(): close(sockfd); Esto previene de hacer prximos reads y writes al Socket. Adems cualquiera que intente un read o write al Socket desde el otro terminal recibir un error. Slo en caso de que quieras ms control sobre el cierre del Socket, puedes usar la funcin Shutdown(). Que te permite cortar la comunicacin en una cierta direccin o en ambas direcciones. int shutdown(int sockfd, int how); sockfd : Es el descriptor de archivo que t deseas cerrar. Int how : Entero que realiza la accin. Ahora, las acciones son: 0 No se permiten prximos recibos. 1 No se permiten prximos envos 2 No se permiten prximos envos, ni recibos. Shutdown() regresa un 1, en caso de error.

Funcin getpeername() Bsicamente es esta funcin quien te dice quin se encuentra el final de la lnea. #include <sys/socket.h> int getpeername(int sockfd, struct sockaddr *addr, int *addrlen); sockfd Es el descriptor de archivo. addr Es el puntero a sockaddr (o a struct sockaddr_in) que almacenar la informacin sobre el otro lado de la conexin. addrlen Es un puntero a int, que otorga la longitud(struct sockaddr). Esta funcin como todas, regresa un 1 si hubo un error.

21

Funcin gethostname() Regresa el nombre del computador donde se est corriendo el programa. Luego se puede usar gethostbyname(), para determinar la IP de tu mquina local. #include <unistd.h> int gethostname(char *hostname, size_t size); hostname Es un puntero a un arreglo de caracteres que contendrn el nombre del Host. size Es la longitud en bytes del arreglo del Host. La Funcin regresa como todas la vistas un 0 si hubo xito y 1 si fracas Ultimos Puntos a Tener en Cuenta Para ya ir terminando, slo nos resta tocar unos cuantos puntos que pueden ser muy necesarios a la hora de poder enfrentarnos con imprevistos y el primero a tener en cuenta es la seal SIGPIPE. Como se mencion, al establecer una conexin, aunque nosotros no estemos enviando datos se transmiten paquetes cada cierto tiempo para verificar que la conexin sigue establecida. Con ello, el protocolo puede detectar que una conexin fue rota, debido a un fallo en la red, en el programa remoto al que nos conectamos, etc. Cuando esto suceda, si intentamos enviar datos por esa conexin rota, nuestro proceso recibir una seal, SIGPIPE. El problema radica ac es que si no capturamos esta seal el comportamiento por defecto es terminar el programa. Por esto si queremos evitarnos que se nos caiga a cada rato nuestra conexin debemos tomar las medidas para reaccionar ante estas eventualidades, o sea, hay que capturar esta seal. Estas seales son una especie de interrupciones de software. Un proceso puede recibir una seal en cualquier momento de su ejecucin y pasar inmediatamente a atenderla. Cuando un proceso recibe una seal, segn cual sea, se ejecutar un manejador, o sea, una funcin que realizar las acciones oportunas. Este proceso podra ser escrito por uno mismo, salvo en los casos de seales como SIGKILL y SIGSTOP, cuya recepcin implica que el proceso se termine o pare. Hay dos casos en los que es recomendable hacerlo siempre: Cuando hagamos hijos que nos enven la seal SIGCHLD para, por lo menos, matarlos y adems realizar las operaciones oportunas de nuestro programa. Cuando usemos flujos de comunicaciones, como Sockets orientados a conexin, debemos entonces obtener la seal para impedir una cada abrupta del programa. Para poder capturar esta seal usamos la funcin signal() Typedef void (*sighandler_t)(int); Void signal(int signal, sighandler_t handler); Por lo que para capturar la seal SIGCHLD haramos: #include<signal.h> void hijos(int signal) {

22

.. cdigo nuestro para cuando se reciba la seal signal(SIGCHLD, hijos); /* Es preciso restablecer nuestro manejador cada vez que se captura la seal*/ } main(){ . signal(SIGCHLD, hijos);

} Cuando el programa recibe una seal y est ejecutndose una llamada al sistema, sta se interrumpir debido a que las llamadas al sistema han de realizarse en forma indivisible. Existe, no obstante, la posibilidad de modificar la forma de comportamiento de las seales para que cuando interrumpan una llamada al sistema sta se reinicie automticamente. Tambin es posible ignorar algunas seales. Esto se logra con las funciones SIGACTION y SIGPROCMASK. Seales ms Importantes SIGKILL No se puede capturar ni ignorar y el proceso muere al recibirla. SIGTERM El comportamiento por defecto es morir, pero se puede capturar o ignorar. SIGPIPE Canal de comunicaciones roto(sin lectores). SIGALARM Seal programable. SIGCHLD Terminacin de un hijo. SIGSTOP Parar la ejecucin del programa. No es capturable, ni ignorable. SIGCONT Continuar con la ejecucin del programa si estaba parado. Temporizaciones Concluyendo ya el trabajo slo resta hacer notar que esto se produce por las llamadas bloqueantes al sistema, y que nos mantienen suspendidos por un tiempo indefinido hasta que ocurra algo que nos permita salir del bloqueo(como que lleguen datos). Pero se puede dar el caso que necesitemos esperar a que llegue un dato por un tiempo limitado, y si no llegase, realizar una accin alternativa. Para esto usamos la funcin select(). Esta funcin trabaja con tres conjuntos de descriptores: Descriptores en los que esperamos aparezcan datos para leer. Descriptores en los que esperamos sea posible escribir datos. Descriptores para posibles excepciones. Tambin durante esta espera se le pasar un puntero a un dato con el tiempo que queremos esperar, pudiendo esperar indefinidamente si en vez de pasar el puntero al parmetro temporal pasamos el valor NULL. EL valor devuelto por select() es el nmero de descriptores que hay en los conjuntos si hubo algn cambio de estado en ellos. Devuelve 0 si expir la temporizacin y 1 si sucedi algn error.

23

Estos descriptores se almacenan en unos structs de tipo fd_set. Para manejarlos existen unas macros que sirven para borrar todos los descriptores del conjunto, para aadir o quitar descriptores y para saber si un descriptor pertenece al conjunto. Esta funcionalidad puede resultar til, pero hay que tener en cuenta que en otros sistemas UNIX select() no est implementado de esta forma. As que, en caso de interesar la portabilidad del cdigo de la aplicacin hay que tener es cuenta esto. Tambin es posible que sea til emplear la funcin select() aunque no queramos realizar temporizaciones. Si, por ejemplo, estamos esperando datos por ms de un sitio(varios Sockets o un Socket y un pipe) podemos usar la funcin select() para esperar a tener datos disponibles por cualquiera de ellos. Si nos quedsemos escuchando por uno, al llegar datos por otro no nos enteraramos y por consiguiente no podramos atender la peticin.

Funcin Select() Int select(int n, fd_set *readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout); N : Es el nmero de descriptores de ficheros ms alto de los conjuntos ms 1. Readfds : Es el conjunto de descriptores para lectura. Writefds : Es el conjunto de descriptores de escritura. Exceptfds : Es el conjunto para ver si ocurren excepciones. Timeout : Contiene el mximo tiempo que se esperar a que ocurra algo. Struct timeval{ Int tv_usev; //Microsegundos Int tv_sec; //segundos } FD_ZERO(fd_set *set); // Deja vaco el conjunto apuntado por set. FD_SET(int fd, fd_set *set); // Aade el descriptor fd al conjunto. FD_CLR(int fd, fd_set *set); // Quita el descriptor fd del conjunto. FD_ISSET(int fd, fd_set *set); // Indica si el descriptor fd pertenece al conjunto. Unos programas de Sockets Bueno he hablado n de esto as que finalizar este trabajo con un par de programas que hacen de cliente y servidor. No los escrib yo, sino que son sacados de aqu http://www.ecst.csuchico.edu/~beej/guide/net. Me ahorr la pega. Todo lo que este servidor hace es enviar la cadena Hello World!", Sobre una conexin Stream. Slo se necesita para testear este servidor, correrlo en una ventana para comunicarte a l desde otra con: 24

$ telnet remotehostname 3490 Donde remotehostname es el nombre de la mquina donde ests corriendo Servidor /* ** server.c a stream socket server demo */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #define MYPORT 3490 /* the port users will be connecting to */ #define BACKLOG 10 /* how many pending connections queue will hold */ main() { int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */ struct sockaddr_in my_addr; /* my address information */ struct sockaddr_in their_addr; /* connector's address information */ int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == 1) { perror("socket"); exit(1); }

25

my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(MYPORT); /* short, network byte order */ my_addr.sin_addr.s_addr = INADDR_ANY; /* automatically fill with my IP */ bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */ if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == 1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == 1) { perror("listen"); exit(1); } while(1) { /* main accept() loop */ sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == 1) { perror("accept"); continue; } printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr)); if (!fork()) { /* this is the child process */ if (send(new_fd, "Hello, world!\n", 14, 0) == 1) perror("send"); close(new_fd); exit(0); } close(new_fd); /* parent doesn't need this */

26

while(waitpid(1,NULL,WNOHANG) > 0); /* clean up all child processes */ } } Programa Cliente Este es mucho ms fcil que el anterior. Todo lo que hace es conectarse al host que especficas en la lnea de comando, puerto 3490. Luego obtiene la cadena que el servidor le enva. /* ** client.c a stream socket client demo */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 3490 /* the port client will be connecting to */ #define MAXDATASIZE 100 /* max number of bytes we can get at once */ int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr; /* connector's address information */ if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); 27

exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */ perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == 1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; /* host byte order */ their_addr.sin_port = htons(PORT); /* short, network byte order */ their_addr.sin_addr = *((struct in_addr *)he>h_addr); bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */ if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == 1) { perror("connect"); exit(1); } if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == 1) { perror("recv"); exit(1); } buf[numbytes] = '\0'; printf("Received: %s",buf); close(sockfd); return 0;

28

} Conclusiones Al trmino de este trabajo. Que en realidad result mucho ms largo de lo que presupuest. Me he encontrado con varias cosas que nunca manej a cabalidad y las definiciones y demases intent, por esto mismo, hacerlas lo ms claras posibles ya que no slo yo quin necesitar echar mano de este trabajo, sino que varios ms se vern en la obligacin de tirar las manos a este trabajo que les ser de gran ayuda. En general podemos concluir que es posible poder construir nosotros mismos los programas que se nos permitan comunicarnos con otros programas y poder mandarles informacin. La forma de realizar esto es mediante los Sockets. Los Sockets concluimos que son una abstraccin para poder definir el punto final de una comunicacin entre interprocesos bidireccionales. Los Sockets son de varios tipos y dependiendo del uso que les queramos dar optaremos por cada uno de ellos. Los Sockets slo pueden comunicarse con Sockets de su mismo tipo y familia, por lo que debemos tener muy claro esto a la hora de querer codificar una transmisin. A travs de nuestros Sockets podemos establecer varias conexiones, pues a partir de un padre el servidor es capaz de crear un hijo, que se encargar de enlazar la informacin, dejando al padre en su tarea de escuchar. Las seales y temporizaciones son un factor a tener en cuenta. Pero tenemos herramientas para poder interactuar con ellas y poder establecer nuestros criterios a la hora de su manejo. No quiero concluir este trabajo sin mencionar que en verdad este tema me tuvo muy apasionado, durante unas buenas semanas( me gust casi tanto como ver Serial Experiments Lain).

Bibliografa Revista Linux Actual, Ao 1 Nmero 9. Tema Programacin de Sockets(I), pginas 52 a 55. Revista Linux Actual, Ao 2 Nmero 10. Tema Programacin de Sockets(II), pginas 53 a 55. Primer on Sockets by Jim Frost (Software Tool & Die) Introductory tutorial on IPC in 4.4BSDUnix (by S.Sechrest UCBerkeley) (Postscript) Advanced tutorial on IPC in 4.4BSDUnix (by S.Leffler, R.Fabry, W.Joy, P.Lampsey UCBerkeley, S.Miller, C.Torek UMaryland) (Postscript) Unixfaq/socket, URL: http://www.ibrado.com/sockfaq/ Programming UNIX Sockets in C Frequently Asked Questions Created by Vic Metcalfe, Andrew Gierth and other contributers, January 22, 1998 Unix Sockets F.A.Q. http://packetstorm.securify.com/programmingtutorials/Sockets/unixsocketfaq.html#toc2 Microsoft Visual Basic 6.0. Fundamentals. Tutorial de Java. 29

http://members.es.tripod.de/froufe/index.html Sockets. Programa en Visual Basic 5.0. http://guille.costasol.net/colabora.htm Beej's Guide to Network Programming Using Internet Sockets Version 1.5.5 (13Jan1999) http://www.ecst.csuchico.edu/~beej/guide/net BDS Sockets : A Quick and Dirty Primer http://www.cs.umn.edu/~bentlema/unix/ Cliente Proceso Hijo Cliente Proceso Hijo Proceso Hijo Cliente Proceso Hijo 2Servidor Cliente Clien Servidor Entrega de Informacin Servidor

30

Cliente Solicitud de Informacin Mensaje Recibido Socket Socket W A N Proceso A Proceso B Datagram Socket Datagram Socket W A N Datagram Socket Datagram Socket

31

32

You might also like