19 de Mayo de 2013
Jun
28

VB.NET ~ Conexiones mediante Sockets

Categorías: ,

Muy buenas a todos. Hoy vamos a ver, como utilizar los sockets para conectar dos aplicaciones. Así que, antes de nada, ¿qué son los sockets?

Un socket, es el elemento más básico en una conexión entre dos aplicaciones que se conectan mediante una red. Es el elemento, a través del cual nosotros podemos establecer esa conexión, recibir y transmitir datos.

Es obligado mencionar, que existen muchos tipos de sockets. Depende del tipo de red que se utilice, y del tipo de servicio que se requiere. Un ejemplo podría ser: Internet como red, y el servicio que requerimos sea que una información llegue a su destino correctamente, sean cuales sean los problemas que nos podamos encontrar en medio (pérdida de información en la red, errores al recibir o enviar la información, etc). En este caso, el socket que deberíamos usar sería un socket TCP.

Esto es un tema complejo, ya que TCP es un protocolo, y nosotros al decir que vamos a tener un socket TCP, estamos diciendo que vamos a usar un socket, y que el programa internamente, sabra como utilizar ese socket para ofrecernos el servicio que define el protocolo TCP.

Hay muchos protocolos, todos definidos para necesidades distintas, o con énfasis en distintos aspectos de la comunicación entre las dos aplicaciones: fiabilidad, rapidez, etc.. Sin embargo, nosotros hoy nos vamos a quedar aquí, pues vamos a utilizar el TCP.

Así pues, sabido ya qué vamos a utilizar para crear la conexión entre dos aplicaciones ¿qué vamos a hacer?

Nuestro objetivo hoy, para mostrar como funcionan los sockets, será crear un par de programas (cliente-servidor), donde el cliente se conectará al servidor (sabiendo previamente en qué dirección IP se encuentra y en que puerto funciona), y le mandará unos mensajes. El servidor no responderá al mensaje, y almacenará los mensajes recibidos en una ventana para que puedan ser leidos por el administrador del ordenador donde se encuentra el servidor.

  • Programa Servidor

Vamos a utilizar un formulario, en el que solo colocaremos dos elementos. Uno será un botón, para poner a funcionar el servidor, y el otro será el textbox donde se irá mostrando los mensajes recibidos del cliente.

Para que no se puedan falsificar los mensajes, vamos a hacer que sea imposible editar el textbox manualmente, editando su evento keypress.

e.KeyChar = ""

Bien, para que el servidor funcione, vamos a necesitar dos variables globales. Una será un Integer, en el que indicaremos cuántos mensajes hemos recibido, o en su defecto el nº del mensaje recibido (1º, 2º..). La segunda, será un TcpListener. Esta clase, representa un socket de tipo TCP, que no sirve para conectar con otra aplicación directamente, sino que es utilizada para que, al querer otra aplicación conectar con nuestro servidor, el TcpListener lo detecte, y con él podamos crear el socket necesario para establecer dicha conexión. Se dice que el socket está a la escucha de conexiones.

Ahora, solo nos queda, poner a funcionar el servidor como tal, al pulsar el botón dedicado a ello. Debemos empezar, poniendo a trabajar el TcpListener, para recibir las conexiones que nos lleguen. Así que primero debemos instanciarlo, y es en ese momento en el que debemos decirle qué IP debe reconocer, y en que puerto queremos trabajar. La IP que debe reconocer, se debe a que un equipo puede ser identificado con diferentes IP: bucle local (127.0.0.1), IP Lan (192.168.*.* o similares), IP Wan, e IP de Redes Virtualizadas (véase Hamachi). Al elegir una de ellas, le estamos diciendo al socket de escucha, que solo queremos aceptar conexiones que vengan dirigidas a nosotros como uno de esos entornos (interfaces), y no desde otros. Por ejemplo, si ponemos el bucle local, solo nosotros podremos conectarnos al servidor desde el mismo PC.

Nosotros vamos a utililizar un método de la clase IPAdress, que le especifica al socket que debe escuchar conexiones de todas las interfaces por las que puedan llegarle: IPAdress.Any. Este método devuelve una IPAdress, que identifica a todas las interfaces al mismo tiempo, por lo que al construir el TcpListener, esta es la IP que debemos pasarle.

Socket_Escucha = New TcpListener(Net.IPAddress.Any, puerto)

Una vez inicializado el socket, solo debemos ponerlo a trabajar con el método start. Este método admite un argumento, que será el nº máximo de conexiones en espera mientras atendemos una conexión.

Socket_Escucha.Start(cantidad)

¡Y listo! Con esto ya tenemos al servidor escuchando conexiones. Es importante remarcar, que aunque el TcpListener este trabajando, nuestro programa no se quedará bloqueado, mientras el TcpListener trabaja. Este lo hará de manera paralela a la ejecución de nuestro programa.

Así pues, debemos pasar a la recepción de conexiones. Para ello, vamos a utilizar el método Pending del TcpListener, que nos indica si hay conexiones pendientes de atender, y en dicho caso, vamos a aceptar la siguiente.

If Socket_Escucha.Pending = True Then

Dim Socket_con_el_Cliente As Socket = oInitSocket.AcceptSocket()

Y con nuestro socket Socket_con_el_Cliente, ya podemos enviar y recibir datos con el cliente. Ahora, como nuestro servidor lo único que hace es recibir, vamos a crear una pequeño array de Bytes como búffer de lectura, donde almacenaremos los mensajes recibidos.

Dim Datos(255) As Byte

Para recibir esos datos, solo necesitamos emplear el método Receive, que tiene la clase Socket. Como argumento, debemos pasarle el búffer donde se van a guardar los datos.

Socket_con_el_Cliente.Receive(Datos)

Estos datos que recibimos, vienen codificados como Bytes. Sin embargo, nosotros sabemos de antemano qué es lo que nos está enviando el cliente. En este caso, estaremos mandando mensajes de texto, por lo que vamos a decodificarlos. Utilizaremos para ello la codificación BigEndianUnicode.

Dim traduccion as String = System.Text.Encoding.BigEndianUnicode.GetString(Datos)

Por último, solo nos queda desconectarnos del cliente una vez recibido el mensaje que esperábamos, para lo que vamos a desconectarnos usando el método Disconnect, y luego liberaremos todos los recursos del socket usando el método Close.

Socket_con_el_Cliente.Disconnect(False)

Socket_con_el_Cliente.Close()

Si vamos a procesar peticiones de clientes sin parar (cosa normal en un servidor), esta parte que hemos programado para aceptar un cliente y recibir sus datos, debemos encajarla en algún tipo de bucle, de manera que se repita constantemente el proceso. Esto bloqueará el programa, y no podremos tocar nada después de pulsar el botón de activación del servidor. Hay formas de evitar esto, pero no se verán en este tutorial: nos conformaremos de momento deteniendo la depuración con VB.NET, para detener el programa.

Descargar ejemplo en VB.Net 2010

Cabe destacar, que en el ejemplo que he subido, hay un par de lineas de código extra no explicadas por aquí, destinadas a que, aunque el programa este bloqueado en el procesamiento de los sockets, escriba en pantalla lo que va recibiendo.
  • Programa Cliente

Bien, pues ahora vamos a hacer el programa, que enviará mensajes al servidor. Basandonos en lo hecho anteriormente con el servidor, utilizaremos un elemento de tipo Socket. A este objeto, debemos especificarle los parámetros de conexión, es decir, la IP y el puerto del equipo al que queremos conectarnos.

Dim Socket_Conexion As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

Bien, al crear este socket, nosotros estamos especificando tres cosas. La primera, AddressFamily, le esta diciendo al programa que nuestro socket está pensando para direcciones de un tipo concreto. Nosotros le estamos diciendo, que utilizaremos direcciones IPv4, a traves del nombre InterNetwork.  A continuación, le estamos diciendo que queremos que el socket sea de tipo Stream, ya que es el tipo de Socket que ofrece los requerimientos que nosotros buscamos. Por último, utilizamos como ya razonamos al principio de este tutorial, el socket de tipo TCP.

A continuación, vamos a necesitar un pequeño Búffer, donde tendremos los datos que queremos enviar. Este buffer será un array de bytes, pues es lo que utilizan los sockets para enviar la información.

Dim Datos(500) As Byte

En este caso, hemos optado por ponerle un límite de 500 Bytes a nuestros mensajes.

Ahora,  vamos a codificar nuestro mensaje a enviar, en Bytes. Para ello, vamos a utilizar la función GetBytes.

Datos = System.Text.Encoding.BigEndianUnicode.GetBytes(TextBox1.Text  )

Es destacable decir, que hemos usado en ambos programas el BigEndianUnicode, con el fin de que los mensajes entre los programas sean legibles. Podríamos haber escogido cualquier otro formato, pero siempre el mismo en ambos programas, si queremos que uno interprete exactamente lo que el otro ha enviado.

Toca conectar con el servidor. Para ello, utilizaremos la función Connect que poseen los sockets. En caso de estar el servidor en nuestro propio ordenador, podemos utilizar:

Socket_Conexion.Connect("localhost", puerto)

Donde el puerto deberá ser el mismo que pusimos en el TcpListener del servidor. Sin embargo, si el servidor no esta (como suele ocurrir) en la misma máquina, debemos usar:

Socket_Conexion.Connect(Net.IPAddress.Parse("IP del servidor"), puerto)

La gracia del asunto recae en la funcion Parse, que cogerá la IP que tengamos del servidor como String, y devolverá el objeto IPAddress que necesita el socket para conectarse.

Así pues, una vez conectados ambosprogramas mediante sockets, ya solo nos queda enviar la información. Esto se hace mediante la función Send:

Socket_Conexion.Send(Datos)

Por último para terminar bien el programa, deberíamos desconectar y cerrar el socket, como hicimos en el servidor.

Descargar ejemplo en VB.Net 2010

Y hasta aquí llegamos hoy. Un saludo a todos

Btc


 

0