Está en la página 1de 9

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

1 de 9

Lo + nuevo

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

Visual Basic 6

ASP.NET
Lenguajes .NET

<Xaml />
Cmo en .NET

Foros

HTML / Scripts
ADO.NET

Windows

Colaboraciones

el Guille, la Web del Visual Basic, C#, .NET y ms...

Utilizando Sockets en
VB .NET
[Enviar y recibir mensajes]
Fecha: 12/Jul/04 (09/07/04)
Autor: Tilli, Pablo D. tillipablo@hotmail.com

Las ofertas
del Guille
para
alojamiento
(hosting) de
sitios web,
seguramente
los mejores
precios del
mercado

Introduccin
Hoy quiero aportar un granito de arena escribiendo mi primer tutorial, para que el intercambio de informacin entre
los desarrolladores siga creciendo da a da. Creo que es necesaria esta divulgacin de conocimientos, ya que como
es mi caso (y supongo el de muchas personas mas) fue uno de mis principales medios de aprendizaje. Si bien
concurro a cursos y a la universidad, este camino tiene otras caractersticas que hacen mucho ms llevadera la
etapa de aprender, permitiendo manejar mejor los tiempos de cada uno.
Bueno, ahora si es hora de explicar un poco de que vamos a hablar en este tutorial. La idea es poder implementar
dos clases: Cliente y Servidor. Probablemente el nombre de las clases digan todo, pero igual voy explicar un poco
mas de que se trata. Un objeto de la clase Cliente, podr conectarse a un objeto de la clase Servidor, permitiendo el
envi de mensajes en los dos sentidos (Cliente a Servidor y Servidor a Cliente).
Esto puede ser til en una gran cantidad de aplicaciones, donde se necesita una comunicacin entre dos o ms
computadoras conectadas en red.

Un poco de teora
Se que esto de la teora muchas veces resulta aburrido, pero la verdad es importante tener una base terica antes
de ponerse a trabajar en el cdigo: Uno no puede codificar lo que no sabe.
Como dije al principio, el objetivo es lograr una conexin entre varias computadoras. Para esto necesitamos algn
medio por el cual se pueda mantener una conversacin entre las mismas. Aqu entran en juego los famosos
Sockets, pero Qu es un socket?

Qu es un socket?
Seguramente habrs escuchado nombrar la palabra Socket muchas veces, y posiblemente te preguntaste que era,
as que intentare sacar tu duda de la manera mas simple: un Socket es una relacin entre un puerto de un equipo y

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

2 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

el puerto de otro equipo. Ahora nombre la palabra puerto, pero de que se trata esto de los puertos?

Qu es un puerto?
Los puertos son bsicamente, una entrada/salida de informacin. Estos se encuentran identificados por un nmero
entero y muchos se encuentran reservados para determinadas tareas, por ejemplo: el puerto 80 es para un servidor
web.

Conclusin
Ahora bien, para que nos sirve saber que es un Socket y un Puerto (Al menos tener una idea de que son). Si
miramos con atencin nos daremos cuenta que es justo lo que necesitamos para nuestro propsito.
Tendremos un objeto de la clase Servidor, que creara un Socket que se quedara escuchando en un puerto que
elijamos nosotros. El servidor seria un extremo del Socket, pero para que un Socket este realmente completo
necesitamos otro extremo, que obviamente sern objetos de la clase Cliente, que se conectaran al puerto del equipo
donde este el objeto servidor.
Si todava no queda del todo claro, slo segu leyendo y todo se ira aclarando de a poco, cuando veamos algo de
cdigo.

Manos a la obra
Antes de mostrar el cdigo, les voy a describir las propiedades, mtodos y eventos de las clases a implementar.

El Servidor
Propiedades
PuertoDeEscucha() As String
Establece/devuelve el puerto donde se quiere que el servidor quede escuchando.

Mtodos
Escuchar()
Inicia el proceso de escuchar peticiones de conexin de parte de los clientes, en el puerto establecido en la
propiedad PuertoDeEscucha.

ObtenerDatos(ByVal IDCliente As Net.IPEndPoint) As String


Obtiene los ltimos datos enviados por el cliente especificado.

Cerrar(ByVal IDCliente As Net.IPEndPoint)


Cierra la conexin con el cliente especificado.

Cerrar()
Cierra todas las conexiones abiertas con los clientes.

EnviarDatos(ByVal IDCliente As Net.IPEndPoint, ByVal Datos As String)


Enva un mensaje al cliente especificado.

EnviarDatos(ByVal Datos As String)


Enva un mensaje a todas los clientes.

Eventos
NuevaConexion(ByVal IDTerminal As Net.IPEndPoint)
Se produce cuando un Cliente se conecta al Servidor, y nos devuelve un ID, para que podamos identificarlo mas
tarde.

DatosRecibidos(ByVal IDTerminal As Net.IPEndPoint)


Se produce cuando un Cliente nos enva un mensaje. Para obtener los datos recibidos, usaremos el mtodo

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

3 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

ObtenerDatos pasndole como parmetro el ID del cliente.

ConexionTerminada(ByVal IDTerminal As Net.IPEndPoint)


Nos avisa que se ha cerrado la conexin con el Cliente recibido como parmetro.

El Cliente
Propiedades
IPDelHost() As String
Establece/devuelve la direccin IP (o el nombre DNS) del equipo donde se encuentra el objeto de la clase
Servidor.

PuertoDelHost() As String
Establece/devuelve el numero de puerto en el que estar escuchando el objeto de la clase Servidor al cual nos
queremos conectar.

Mtodos
Conectar()
Permite conectarse al objeto Servidor que se encuentra escuchando en la direccin especificada por la propiedad
IPDelHost en el puerto establecido en la propiedad PuertoDelHost.

EnviarDatos(ByVal Datos As String)


Enva un mensaje al objeto de la clase Servidor a la que se este conectado.

Eventos
ConexionTerminada()
Se produce cuando se termina la conexin con el objeto Servidor.

DatosRecibidos(ByVal Datos As String)


Nos avisa que el servidor nos ha enviado un mensaje, y el mismo se encuentra en el parmetro Datos.

Al fin, ahora si llego la hora de ver cdigo empecemos.

Cdigo de la clase Servidor


Imports
Imports
Imports
Imports
Imports

System
System.Threading
System.Net.Sockets
System.IO
System.Text

Public Class WinSockServer


#Region "ESTRUCTURAS"
Private Structure InfoDeUnCliente
'Esta estructura permite guardar la informacin sobre un cliente
Public Socket As Socket 'Socket utilizado para mantener la conexion con el cliente
Public Thread As Thread 'Thread utilizado para escuchar al cliente
Public UltimosDatosRecibidos As String 'Ultimos datos enviados por el cliente
End Structure
#End Region
#Region "VARIABLES"
Private tcpLsn As TcpListener
Private Clientes As New Hashtable() 'Aqui se guarda la informacion de todos los clientes
conectados
Private tcpThd As Thread
Private IDClienteActual As Net.IPEndPoint 'Ultimo cliente conectado
Private m_PuertoDeEscucha As String

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

4 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

#End Region
#Region "EVENTOS"
Public Event NuevaConexion(ByVal IDTerminal As Net.IPEndPoint)
Public Event DatosRecibidos(ByVal IDTerminal As Net.IPEndPoint)
Public Event ConexionTerminada(ByVal IDTerminal As Net.IPEndPoint)
#End Region
#Region "PROPIEDADES"
Property PuertoDeEscucha() As String
Get
PuertoDeEscucha = m_PuertoDeEscucha
End Get
Set(ByVal Value As String)
m_PuertoDeEscucha = Value
End Set
End Property
#End Region
#Region "METODOS"
Public Sub Escuchar()
tcpLsn = New TcpListener(PuertoDeEscucha)
'Inicio la escucha
tcpLsn.Start()
'Creo un thread para que se quede escuchando la llegada de un cliente
tcpThd = New Thread(AddressOf EsperarCliente)
tcpThd.Start()
End Sub
Public Function ObtenerDatos(ByVal IDCliente As Net.IPEndPoint) As String
Dim InfoClienteSolicitado As InfoDeUnCliente
'Obtengo la informacion del cliente solicitado
InfoClienteSolicitado = Clientes(IDCliente)
ObtenerDatos = InfoClienteSolicitado.UltimosDatosRecibidos
End Function
Public Sub Cerrar(ByVal IDCliente As Net.IPEndPoint)
Dim InfoClienteActual As InfoDeUnCliente
'Obtengo la informacion del cliente solicitado
InfoClienteActual = Clientes(IDCliente)
'Cierro la conexion con el cliente
InfoClienteActual.Socket.Close()
End Sub
Public Sub Cerrar()
Dim InfoClienteActual As InfoDeUnCliente
'Recorro todos los clientes y voy cerrando las conexiones
For Each InfoClienteActual In Clientes.Values
Call Cerrar(InfoClienteActual.Socket.RemoteEndPoint)
Next
End Sub
Public Sub EnviarDatos(ByVal IDCliente As Net.IPEndPoint, ByVal Datos As String)
Dim Cliente As InfoDeUnCliente
'Obtengo la informacion del cliente al que se le quiere enviar el mensaje
Cliente = Clientes(IDCliente)
'Le envio el mensaje
Cliente.Socket.Send(Encoding.ASCII.GetBytes(Datos))
End Sub
Public Sub EnviarDatos(ByVal Datos As String)
Dim Cliente As InfoDeUnCliente
'Recorro todos los clientes conectados, y les envio el mensaje recibido
'en el parametro Datos
For Each Cliente In Clientes.Values
EnviarDatos(Cliente.Socket.RemoteEndPoint, Datos)
Next
End Sub

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

5 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

#End Region
#Region "FUNCIONES PRIVADAS"
Private Sub EsperarCliente()
Dim InfoClienteActual As InfoDeUnCliente
With InfoClienteActual
While True
'Cuando se recibe la conexion, guardo la informacion del cliente
'Guardo el Socket que utilizo para mantener la conexion con el cliente
.Socket = tcpLsn.AcceptSocket() 'Se queda esperando la conexion de un cliente
'Guardo el el RemoteEndPoint, que utilizo para identificar al cliente
IDClienteActual = .Socket.RemoteEndPoint
'Creo un Thread para que se encargue de escuchar los mensaje del cliente
.Thread = New Thread(AddressOf LeerSocket)
'Agrego la informacion del cliente al HashArray Clientes, donde esta la
'informacion de todos estos
SyncLock Me
Clientes.Add(IDClienteActual, InfoClienteActual)
End SyncLock
'Genero el evento Nueva conexion
RaiseEvent NuevaConexion(IDClienteActual)
'Inicio el thread encargado de escuchar los mensajes del cliente
.Thread.Start()
End While
End With
End Sub
Private
Dim
Dim
Dim
Dim

Sub LeerSocket()
IDReal As Net.IPEndPoint 'ID del cliente que se va a escuchar
Recibir() As Byte 'Array utilizado para recibir los datos que llegan
InfoClienteActual As InfoDeUnCliente 'Informacion del cliente que se va escuchar
Ret As Integer = 0

IDReal = IDClienteActual
InfoClienteActual = Clientes(IDReal)
With InfoClienteActual
While True
If .Socket.Connected Then
Recibir = New Byte(100) {}
Try
'Me quedo esperando a que llegue un mensaje desde el cliente
Ret = .Socket.Receive(Recibir, Recibir.Length, SocketFlags.None)
If Ret > 0 Then
'Guardo el mensaje recibido
.UltimosDatosRecibidos = Encoding.ASCII.GetString(Recibir)
Clientes(IDReal) = InfoClienteActual
'Genero el evento de la recepcion del mensaje
RaiseEvent DatosRecibidos(IDReal)
Else
'Genero el evento de la finalizacion de la conexion
RaiseEvent ConexionTerminada(IDReal)
Exit While
End If
Catch e As Exception
If Not .Socket.Connected Then
'Genero el evento de la finalizacion de la conexion
RaiseEvent ConexionTerminada(IDReal)
Exit While
End If
End Try
End If
End While

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

6 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

Call CerrarThread(IDReal)
End With
End Sub
Private Sub CerrarThread(ByVal IDCliente As Net.IPEndPoint)
Dim InfoClienteActual As InfoDeUnCliente
'Cierro el thread que se encargaba de escuchar al cliente especificado
InfoClienteActual = Clientes(IDCliente)
Try
InfoClienteActual.Thread.Abort()
Catch e As Exception
SyncLock Me
'Elimino el cliente del HashArray que guarda la informacion de los clientes
Clientes.Remove(IDCliente)
End SyncLock
End Try
End Sub
#End Region
End Class

Cdigo de la clase Cliente


Imports
Imports
Imports
Imports
Imports
Imports

System
System.Net
System.Net.Sockets
System.Threading
System.Text
System.IO

Public Class Cliente


#Region "VARIABLES"
Private Stm As Stream 'Utilizado para enviar datos al Servidor y recibir datos del mismo
Private m_IPDelHost As String 'Direccion del objeto de la clase Servidor
Private m_PuertoDelHost As String 'Puerto donde escucha el objeto de la clase Servidor
#End Region
#Region "EVENTOS"
Public Event ConexionTerminada()
Public Event DatosRecibidos(ByVal datos As String)
#End Region
#Region "PROPIEDADES"
Public Property IPDelHost() As String
Get
IPDelHost = m_IPDelHost
End Get
Set(ByVal Value As String)
m_IPDelHost = Value
End Set
End Property
Public Property PuertoDelHost() As String
Get
PuertoDelHost = m_PuertoDelHost
End Get
Set(ByVal Value As String)
m_PuertoDelHost = Value
End Set
End Property
#End Region
#Region "METODOS"
Public Sub Conectar()
Dim tcpClnt As TcpClient
Dim tcpThd As Thread 'Se encarga de escuchar mensajes enviados por el Servidor
tcpClnt = New TcpClient()
'Me conecto al objeto de la clase Servidor,

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

7 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

' determinado por las propiedades IPDelHost y PuertoDelHost


tcpClnt.Connect(IPDelHost, PuertoDelHost)
Stm = tcpClnt.GetStream()
'Creo e inicio un thread para que escuche los mensajes enviados por el Servidor
tcpThd = New Thread(AddressOf LeerSocket)
tcpThd.Start()
End Sub
Public Sub EnviarDatos(ByVal Datos As String)
Dim BufferDeEscritura() As Byte
BufferDeEscritura = Encoding.ASCII.GetBytes(Datos)
If Not (Stm Is Nothing) Then
'Envio los datos al Servidor
Stm.Write(BufferDeEscritura, 0, BufferDeEscritura.Length)
End If
End Sub
#End Region
#Region "FUNCIONES PRIVADAS"
Private Sub LeerSocket()
Dim BufferDeLectura() As Byte
While True
Try
BufferDeLectura = New Byte(100) {}
'Me quedo esperando a que llegue algun mensaje
Stm.Read(BufferDeLectura, 0, BufferDeLectura.Length)
'Genero el evento DatosRecibidos, ya que se han recibido datos desde el
Servidor
RaiseEvent DatosRecibidos(Encoding.ASCII.GetString(BufferDeLectura))
Catch e As Exception
Exit While
End Try
End While
'Finalizo la conexion, por lo tanto genero el evento correspondiente
RaiseEvent ConexionTerminada()
End Sub
#End Region
End Class

Cmo utilizar las clases?


Bueno, hemos terminado con lo que se refiere al cdigo de las clases Cliente y Servidor, pero antes de terminar con
el tutorial vamos a ver un pequeo ejemplo de como utilizarlas. En mi caso tengo la clase Cliente por un lado
(Cliente.dll) y el Servidor por el otro (Servidor.dll). Lo que vamos ha hacer en este ejemplo es crear dos pequeas
aplicaciones donde una se quede escuchando (El Servidor), y otra que se conecta a la que escucha (Cliente). Ambas
podrn enviar y recibir mensajes.

Aplicacin Servidor

Nota: Se debe establecer una referencia a Servidor.dll.


Public Class Form1
Inherits System.Windows.Forms.Form
" Cdigo generado por el Diseador de Windows Forms "
Dim WithEvents WinSockServer As New Servidor()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
MyBase.Load

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

8 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

With WinSockServer
'Establezco el puerto donde escuchar
.PuertoDeEscucha = 8050
'Comienzo la escucha
.Escuchar()
End With
End Sub
Private Sub WinSockServer_NuevaConexion(ByVal IDTerminal As System.Net.IPEndPoint) Handles
WinSockServer.NuevaConexion
'Muestro quien se conecto
MsgBox("Se ha conectado un nuevo cliente desde la IP= " & IDTerminal.Address.ToString &
_
",Puerto = " & IDTerminal.Port)
End Sub

Private Sub WinSockServer_ConexionTerminada(ByVal IDTerminal As System.Net.IPEndPoint)


Handles WinSockServer.ConexionTerminada
'Muestro con quien se termino la conexion
MsgBox("Se ha desconectado el cliente desde la IP= " & IDTerminal.Address.ToString & _
",Puerto = " & IDTerminal.Port)
End Sub
Private Sub WinSockServer_DatosRecibidos(ByVal IDTerminal As System.Net.IPEndPoint) Handles
WinSockServer.DatosRecibidos
'Muestro quien envio el mensaje
MsgBox("Nuevo mensaje desde el cliente de la IP= " & IDTerminal.Address.ToString & _
",Puerto = " & IDTerminal.Port )
'Muestro el mensaje recibido
Call MsgBox(WinSockServer.ObtenerDatos(IDTerminal))
End Sub
Private Sub btnEnviarMensaje_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnEnviarMensaje.Click
'Envio el texto escrito en el textbox txtMensaje a todos los clientes
WinSockServer.EnviarDatos(txtMensaje.Text)
End Sub
End Class

Aplicacin Cliente

Nota: Se debe establecer una referencia a Cliente.dll.


Public Class Form1
Inherits System.Windows.Forms.Form
" Cdigo generado por el Diseador de Windows Forms "
Dim WithEvents WinSockCliente As New Cliente
Private Sub btnConectar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles btnConectar.Click
With WinSockCliente
'Determino a donde se quiere conectar el usuario
.IPDelHost = txtIP.Text
.PuertoDelHost = txtPuerto.Text
'Me conecto
.Conectar()
'Deshabilito la posibilidad de conexion

15/07/2015 22:44

Colabora.NET: Utilizando Sockets en VB .NET - Tilli, Pablo D.

9 de 9

http://www.elguille.info/colabora/puntoNET/PabloTilli_SocketsVBNE...

txtIP.Enabled = False
txtPuerto.Enabled = False
btnConectar.Enabled = False

'Habilito la posibilidad de enviar mensajes


btnEnviarMensaje.Enabled = True
txtMensaje.Enabled = True
End With
End Sub
Private Sub WinSockCliente_DatosRecibidos(ByVal datos As String) Handles
WinSockCliente.DatosRecibidos
MsgBox("El servidor envio el siguiente mensaje: " & datos)
End Sub
Private Sub WinSockCliente_ConexionTerminada() Handles WinSockCliente.ConexionTerminada
MsgBox("Finalizo la conexion")
'Habilito la posibilidad de una reconexion
txtIP.Enabled = True
txtPuerto.Enabled = True
btnConectar.Enabled = True
'Deshabilito la posibilidad de enviar mensajes
btnEnviarMensaje.Enabled = False
txtMensaje.Enabled = False
End Sub
Private Sub btnEnviarMensaje_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnEnviarMensaje.Click
'Envio lo que esta escrito en la caja de texto del mensaje
WinSockCliente.EnviarDatos(txtMensaje.Text)
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
End
End Sub
End Class

Conclusin
Como conclusin, creo que si bien queda bastante por hacer (Validaciones, agregar mayor funcionalidad a las clases,
etc.) este tutorial puede ser considerado como una introduccin a la utilizacin de Sockets, que cubre lo bsico para
lograr una comunicacin entre aplicaciones que se encuentran en distintas computadoras.
Quisiera que cualquier duda, sugerencia, crtica, mejora o cualquier otra cosa, me la hagan llegar mi correo
electrnico (tillipablo@hotmail.com).
Espero, que este tutorial sea el primero de una larga lista, y espero tambin que a partir de las crticas que vaya
recibiendo, pueda ir mejorando la manera de presentar el tutorial.

15/07/2015 22:44