0 penilaian0% menganggap dokumen ini bermanfaat (0 suara)
251 tayangan13 halaman
Este documento introduce los sockets en Delphi. Explica que los sockets permiten establecer conexiones entre un cliente y un servidor para enviar y recibir datos a través de TCP/IP. Detalla cómo crear sockets cliente y servidor en Delphi, establecer y cerrar las conexiones, y comprobar el estado de la conexión. Finalmente, cubre cómo enviar y recibir datos a través de los sockets una vez establecida la conexión.
Este documento introduce los sockets en Delphi. Explica que los sockets permiten establecer conexiones entre un cliente y un servidor para enviar y recibir datos a través de TCP/IP. Detalla cómo crear sockets cliente y servidor en Delphi, establecer y cerrar las conexiones, y comprobar el estado de la conexión. Finalmente, cubre cómo enviar y recibir datos a través de los sockets una vez establecida la conexión.
Este documento introduce los sockets en Delphi. Explica que los sockets permiten establecer conexiones entre un cliente y un servidor para enviar y recibir datos a través de TCP/IP. Detalla cómo crear sockets cliente y servidor en Delphi, establecer y cerrar las conexiones, y comprobar el estado de la conexión. Finalmente, cubre cómo enviar y recibir datos a través de los sockets una vez establecida la conexión.
Introduccin. Hace poco, una persona que quera programar un desbordamiento de buffer me mand un mail preguntndome (indirectamente y con muchos rodeos y engaos) cmo hacerlo. Casi me muero de la risa al leer su cdigo. Una vez corregido, se lo envi de vuelta, y entonces me dice que no puede hacerse, que los sockets en Delphi estn mal programados. Lo que tiene uno que or a estas alturas de la vida. Intrigado, me puse a investigar un poco mas, constatando que todo funciona bien. De paso escrib esta pequea gua. Este artculo no est escrito para gente que no tenga una base programando, bien en Delphi, bien en otros lenguajes, sino para aquellas personas que ya sepan programar y quieran enterarse de una forma clara de como establecer una conexin usando Delphi. Espero que sirva de ayuda, porque para eso lo escrib. Enrique Gonzlez Alonso-Buenaposada. webmaster@lanssl.com ndice: 1. Sockets. 2. Cliente, servidor y puertos que intervienen. 3. Crear un socket en Delphi. 3.1. Crear un Socket servidor. 3.2 Crear un socket cliente. 4. Conectar y desconectar los sockets. 4.1. Activar el servidor. 4.2. Conectar el cliente. 4.3. Comprobar si ya estamos conectados. 4.4. La propiedad Active. 5. Obtener informacin de la conexin. 6. Enviar y recibir informacin a travs de los sockets. 6.1. Conexiones Blocking y Non-Blocking. 6.2. Enviar y recibir datos. 6.3. Consejos para programar una aplicacin. 7. El programa de demostracin. 8. Para saber ms. 1. Sockets. Es muy comn escuchar frases como En TCP-IP, todo funciona con sockets.. Menuda frasecita!. Si buscamos la palabra Socket en un diccionario de ingls nos dir que es un agujero o abertura al que se puede enchufar algo(Como el zcalo en el que enchufamos el procesador a la placa base). Esta es una traduccin hecha a lo bestia, pero nos bastar, porque un socket es una especie de enchufe. La palabra con la que yo lo designara es conector. El Socket en todo caso, puede considerarse como el extremo de una conexin. Una vez establecida la conexin entre un cliente y un servidor, usamos los sockets para enviar o recibir datos indistintamente. Este asunto no necesita mas explicacin de momento, los detalles se vern mas adelante. 2. Cliente, servidor y puertos que intervienen. Lo primero que hay que explicar es cmo se establece una conexin en TCP- IP. Aunque parezca que no viene mucho al caso, mas adelante quedar claro el porqu. Lejos de mi intencin explicar todo el proceso de la transmisin pero creo que es importante explicar como se establece la conexin. Supongamos que tenemos montada una intranet con TCP/IP y supongamos que nuestro ordenador cliente (IP 192.168.3.127) quiere establecer una conexin con un servidor de la misma intranet (IP 192.168.3.100) a travs de HTTP (Generalmente puerto 80). Puertos Servicio 0-1023 Puertos Cliente: 1024-65536 Puertos Servicio 0-1023 Puertos Cliente: 1024-65536 SYN ACK Puerto X Puerto 80 SYN/ACK Cliente Servidor Lo primero que har el ordenador cliente ser enviar un paquete de informacin, conocido como SYN, en el que se envan datos tales como su propia direccin IP y el puerto de origen al servidor. Los puertos del cliente los asigna automticamente el sistema operativo(En adelante S.O.) del mismo, y estarn en el rango que hay entre 2 10 (1024) y 2 16 (65536). La peticin va dirigida a un puerto concreto del servidor, en este caso el 80(HTTP). El servidor, naturalmente, est escuchando por el puerto 80. Y cuando recibe el paquete SYN, enva de vuelta un paquete llamado SYN/ACK, que podran explicarse en realidad como dos paquetes. En primer lugar explicaremos ACK, que es la abreviatura de ACKNOWLEDGED, con la que informa al cliente que se ha enterado del paquete SYN que ha recibido. A la vez, enva un paquete SYN como el que el cliente ha enviado. Este paquete SYN/ACK se enva a la direccin IP y puerto de la que provena el primer paquete SYN, por el que se supone estar escuchando el cliente. Hay que hacer notar, que ese puerto estara normalmente cerrado, pero que el S.O. del cliente lo abre para hacer la peticin. Finalmente el cliente enva al servidor un paquete ACK al servidor, indicndole que ha recibido a su vez el paquete SYN/ACK. Si todo este ciclo se completa, la conexin ha quedado establecida en los dos sentidos. Esto es importante, ya que en una conexin se puede leer y escribir a la vez de forma asncrona. Conclusin: En este caso hipottico, quedan fijadas las IPs y los puertos. La IP del cliente a 192.168.3.127, la del servidor a 192.168.3.100. El puerto cliente(en el idem) ser variable asignndolo el S.O. en su momento, pero quedando fijo mientras dure la conexin. El puerto de servicio(en el servidor) ser fijo. El puerto de servicio estar activo solo mientras dure la conexin, mientras que el del servidor permanecer a la escucha atento a otras peticiones (bien desde la misma mquina, o desde otras). 3. Crear un socket en Delphi. Como Delphi es un lenguaje orientado a objetos, todas las operaciones de sockets se realizarn recurriendo a una clase, TclientWinSocket, que es un puerto a las Dlls que usa el S.O. para establecer conexiones. Sin embargo para mayor comodidad, existen las clases TclientSocket y TserverSocket, que descienden de ella, y nos permiten implementar en cada caso, una conexin cliente o servidor. Ambas pueden encontrarse en la paleta de componentes, en la pestaa Internet. Para incluir un objeto de una de estas clases en nuestro programa, bastar con incluir uno de estos componentes. Atencin: Hay que tener muy claro que clase de socket queremos crear, bin cliente, bin servidor. Aunque desde ambos se puede enviar y recibir, es necesario la existencia del primero para que funcione el segundo. Si no tienes claro que es un cliente y que es un servidor, vuelve a leerte el punto anterior (2) de este artculo. 3.1. Crear un Socket servidor. El dato mas importante, en el caso del socket servidor es el del puerto, ya que una vez activado el mismo, este quedar Escuchando, de forma que le introducimos el puerto deseado en el object inspector, o directamente: ServerSocket1.Port:=80; // Por ejemplo. Atencin: Hay que tener en cuenta que si nuestro ordenador tiene otros servidores corriendo, estos pueden estar ocupando ya los puertos que queremos usar. Por ejemplo, si estuviese funcionando un servidor apache (HTTP), con casi toda probabilidad el puerto 80 estara ocupado (Puede configurarse para otro puerto, pero no es habitual). Los programas peer-to-peer y las webcam tambin suelen reservar puertos especficos, ya que establecen conexiones en modo servidor. Los puertos utilizados (normalmente) por los servidores ms comunes son: Puerto Servicio ftp 21 Ssh 22 Telnet 23 Smtp 25 Dns 42 Http 80 Pop3 110 Irc 194 Imap 220 Https 443 Imaps 993 Pop3s 995 Aunque esto puede variar ya que muchos de estos servidores se pueden configurar para utilizar otros puertos distintos. Adems, existen muchos ms puertos utilizados por otros servicios. La lista completa de los puertos utilizados por los distintos servicios puede encontrarse en: http://www.iana.org/assignments/port-numbers No obstante, si lo que tenemos es un windows domstico (95-98-ME-XP), no habr que complicarse demasiado la existencia, bastando con que el puerto de servicio sea un nmero mayor que 20. 3.2 Crear un socket cliente. Para este, el dato mas importante es la IP a la que queremos conectar, junto al puerto del servidor, que esperamos que est escuchando. La IP se la podemos dar en el object inspector, aunque es mejor hacerlo en tiempo de ejecucin, ya que un cliente debera conectarse en tiempo de ejecucin. Lo mismo puede decirse del puerto. ClientSocket1.Address:= 192.168.3.127; // Por ejemplo ClientSocket1.Port:=80; // Por ejemplo. 4. Conectar y desconectar los sockets. Bin, hasta ahora hemos visto que para crear una aplicacin que tenga un socket cliente o servidor bastar con incluirlo desde la paleta de componentes. Tambin hemos visto como darle los valores necesarios. Todo ello es bastante simple si se tiene claro lo que se est haciendo. Crear la conexin es sencillo tambin. 4.1. Activar el servidor. Para activar el servidor, bastar con usar el procedimiento open: ServerSocket1.port:=80; // Damos el puerto. ServerSocket1.Open; // Conectamos. De esta forma el puerto que hayamos elegido para la conexin quedar Escuchando en espera de una conexin. Para desactivarlo usaremos el procedimiento close. ServerSocket1.close; 4.2. Conectar el cliente. Al igual que ocurre con el servidor para conectar y desconectar el cliente usaremos los procedimientos Open y Close: ClientSocket1.Address:= 192.168.3.127; // Le damos una IP ClientSocket1.Port:=80; // Especificamos el puerto al que debe // conectarse. ClientSocket1.Open; // Abrimos la conexin. : : : ClientSocket1.Close; // Cerramos la conexin. Si el servidor no estuviese escuchando, o no nos permitiese la conexin, recibiramos el error de socket correspondiente. 4.3. Comprobar si ya estamos conectados. Para comprobar si ya estamos conectados, bastar con consultar el flag Connected del tipo boolean, que estar en TRUE si la conexin ya est establecida, y a False de no ser as. Esto nos puede evitar, por ejemplo, conectar el cliente si ya est conectado: If not ClientSocket1.Socket.Connected then Clientsocket1.Open; 4.4. La propiedad Active. Otra forma abrir la conexin es que nuestro socket est activo desde que arranca la aplicacin. Para ello usaremos la propiedad Active, que encontramos en el Object Inspector y que normalmente est puesta a FALSE. Si nuestro socket es servidor ACTIVE=TRUE har que est escuchando desde el inicio de la aplicacin. Si es cliente, intentar establecer la conexin desde el inicio. Otra cosa que podemos hacer es con active es cerrar las conexiones. Si ponemos (en tiempo de ejecucin) ACTIVE=FALSE la conexin abierta se cerrar. Si lo hacemos sobre un socket servidor, adems, cerrar todas las conexiones activas (Puede tener varias), haciendo que deje de escuchar por el puerto que le habamos asignado. 5. Obtener informacin de la conexin. Una vez la conexin est establecida, podemos usar las propiedades LocalHost y LocalPort para obtener la direccin IP y el puerto usados por ambos, cliente y servidor. Tambin se puede usar la propiedad Handle para obtener un controlador directo a la conexin. 6. Enviar y recibir informacin a travs de los sockets. Esta es la parte mas complicada (a mi entender) de todo el asunto. Lo es porque la gama de posibilidades es enorme, y todas ellas son correctas para un uso concreto. Explicarlas todas escapa a la intencin de este artculo, de forma que intentar explicar las principales por encima. No obstante recomiendo al lector que busque mas informacin y experimente, dependiendo de sus necesidades. 6.1. Conexiones Blocking y Non-Blocking. Como qued dicho anteriormente al final del captulo 2, la lectura y escritura pueden funcionar de forma independiente una de la otra. Esto es posible en las conexiones non-blocking. En las conexiones Blocking, nos encontramos que hasta que no haya terminado una operacin (Bin de lectura o escritura) no se puede realizar la siguiente. La propiedad que determina que tipo de conexin estamos usando, en cada caso, se llama ClientType para un socket cliente y ServerType para un servidor. Esta propiedad la podemos encontrar en el Object Inspector. 6.2. Enviar y recibir datos. Lo primero que hay que tener en cuenta es el tipo de informacin que se quiere enviar o recibir. Si vamos a leer algo realmente grande, podemos usar mtodos como SendBuf/ReceiveBuf o SendStream/ReceiveStream. Como no es mi intencin explicar como funcionan los buffers y streams, no explicar mas estos mtodos. El lector que sepa como funcionan estas formas de trabajar con datos no tendr dificultad en usar con estos mtodos una vez haya concluido este captulo. Readln/SendLn es otra forma de enviar datos. Se envan y se reciben datos hasta que aparece un carcter especificado como parmetro, aunque personalmente prefiero SendText/ReceiveText. ClientSocket1.Socket.SendText (st); SendText/ReceiveText se puede enviar el contenido de una variable del tipo String. Como las variables de este tipo tienen un tamao dinmico, se pueden usar para enviar casi cualquier cosa. En una variable de este tipo podemos cargar un archivo de cualquier tipo, que quedar idntico al grabarlo. Mediante este procedimiento he llegado a enviar y recibir un archivo de 40 mb sin problemas (Se cada vez mas lento a partir de los 4 mb, pero en general funcionaba bien.). No obstante, para cosas grandes, recomiendo evitar las chapuzas y emplear variables del tipo stream, con las que podemos enviar directamente desde un archivo. Recibir es un poco mas complejo, pero solamente un poco. Como nuestro socket queda establecido, tenemos que esperar a un evento del tipo ClientRead. Crearemos el procedimiento asociado con el Object Inspector, que tendra el siguiente aspecto: procedure TForm1.ClientSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var st:string; begin st:=Socket.ReceiveText; // Ojo, tener en cuenta que se recibe : // de Socket.ReceiveText : // no de ClientSocket1.socket.ReceiveText : // la razn hay que buscarla en el : // encabezado del procedimiento end; 6.3. Consejos para programar una aplicacin. Como se ha visto, el socket es el extremo de una conexin, a travs del cual se pueden enviar y recibir datos. Esto tiene varias aplicaciones, no solamente enviar datos a travs de la red, sino por ejemplo el envo de datos entre dos aplicaciones que estn funcionando en el mismo ordenador. Es fundamental que haya un servidor adecuado funcionando para probar una aplicacin cliente. Esto plantea un problema. Cmo programar, por ejemplo, un cliente apache si solamente disponemos de un ordenador? La respuesta es sencilla, usaremos la IP de intranet de nuestro propio ordenador. Ponemos el servidor a funcionar en nuestra mquina mientras se programa la aplicacin. Qu no tenemos una intranet montada? No hay problema, podemos hacer lo mismo, empleando la IP de loopback que tenga la mquina, normalmente 127.0.0.1. Con esta IP, normalmente estaremos accediendo a nuestro mismo ordenador. Otra cosa a tener en cuenta, es que a la hora de programar un servidor deberamos evitar que haya varias instancias del mismo funcionando. Esto puede hacerse de varias formas. Tambin es muy importante no dejar los sockets abiertos cuando la aplicacin finalice. 7. El programa de demostracin. El programa que se incluye con este artculo pone en marcha un socket cliente y uno servidor. Con el cliente se enva informacin (texto), mientras que con el servidor se recibe. Al incluir los dos sockets, el programa puede intercambiar texto con otro programa en otro ordenador. Lo he probado tanto con la IP 127.0.0.1, como con la direccin de la misma mquina en la intranet. En ambos casos, lo escrito en el memorando de la izquierda se transmite al de la derecha. Tambin est probado desde varias direcciones de una intranet, pudiendo intercambiar texto con otros ordenadores. Para hacerlo as, el servidor al que vamos a conectar debe estar encendido (Una copia del programa corriendo). Escribimos la IP de nuestro objetivo, pulsamos el botn Conectar y ya est listo para enviar texto. El programa evita que se ejecuten varias instancias del mismo recurriendo a un semforo (Ver archivo dpr). El socket servidor arranca con el evento OnCreate del formulario principal, mientras que el cliente (el que enva texto) solamente enva una vez se haya escrito una IP (Correcta) y se pulse el botn conectar. El programa se pens originalmente para intercambiar texto entre dos ordenadores, pero el funcionamiento del mismo permite interconexiones extraas, como por ejemplo: A E D C B En donde el ordenador A no recibe texto de nadie y enva a B. B recibe de A, y enva a C. D y E intercambian entre ellos, pero E recibe tambin de C. Por ltimo debe observarse que se usa el evento OnClose del formulario principal para cerrar los sockets. No explicar mas la aplicacin ya que despus de estas explicaciones, bastar con echarle un vistazo al mismo para comprender que hace y como funciona. 8. Para saber mas. En este artculo se puede leer una introduccin al uso de sockets en Delphi, pero que nadie piense que est todo dicho. En el no est ni la mitad de lo que yo mismo s, y por supuesto hay personas que saben mucho mas del tema que yo. Lo que hay aqu escrito, como el propio ttulo del artculo sugiere, no es mas que una breve introduccin a este tema. Si alguien quiere saber mas, le recomiendo que empiece por la propia ayuda del Borland Delphi, pero que no pare ah. Para continuar, podemos echar un buen vistazo al cdigo fuente de algunos componentes incluidos en el propio Delphi, como los INDY components, que son un buen ejemplo de cmo implementar los protocolos mas comunes usando sockets. El cdigo fuente de algunos programas peer-to-peer puede ser otro buen sitio para aprender, si a uno no le importa ver cdigo escrito para otros compiladores. Todos ellos trabajan con las mismas dlls de Windows. Y por supuesto existen toneladas de literatura al respecto. Desde artculos como este hasta libros dedicados al tema. En todos ellos se hace un estudio mas detallado sobre los temas tratados en este artculo y de otros que se han quedado en el tintero.