Utilizamos cookies propias y de terceros. Al navegar entendemos que aceptas el uso de cookies. +Info.
Política de cookies
Proyecto AjpdSoft

· Inicio
· Buscar
· Contactar
· Cookies
· Descargas
· Foros
· Historia
· Nosotros
· Temas
· Top 10
· Trucos
· Tutoriales
· Usuario
· Wiki

Nick


Contraseña


Nuevo usuario


English

Redes: Socket Visual Basic .Net, conexión mediante socket VB.Net y System.Net.Sockets
Visual Studio .NET


Explicamos cómo conectar dos PCs a través de Internet usando Socket, realizamos un ejemplo de chat entre un PC servidor y sus clientes usando Microsoft Visual Basic .Net (VB.Net) y el Namespace System.Net.Sockets. Mostramos también como comparativa cómo se realizaba una conexión por Socket usando el antiguo lenguaje de programación Visual Basic 6, mediante Winsock.



 

Socket de Internet

Con Socket se designa un concepto abstracto por el cual dos programas situados en computadoras distintas (o en la misma) pueden intercambiar cualquier flujo de datos, generalmente de manera fiable y ordenada.

El término socket es también usado como el nombre de una interfaz de programación de aplicaciones (API) para el stack de protocolos de Internet TCP/IP, provista usualmente por el sistema operativo.

Los sockets de Internet constituyen el mecanismo para la entrega de paquetes de datos provenientes de la tarjeta de red a los procesos o hilos apropiados. Un socket queda definido por un par de direcciones IP local y remota, un protocolo de transporte y un par de números de puerto local y remoto.

Para que dos programas puedan comunicarse entre sí es necesario que se cumplan ciertos requisitos:

  • Que un programa sea capaz de localizar al otro.
  • Que ambos programas sean capaces de intercambiarse cualquier secuencia de octetos, es decir, datos relevantes a su finalidad.

Para ello son necesarios los tres recursos que originan el concepto de socket:

  • Un protocolo de comunicaciones, que permite el intercambio de octetos.
  • Un par de direcciones del protocolo de red (dirección IP, si se utiliza el protocolo TCP/IP), que identifican la computadora de origen y la remota.
  • Un par de números de puerto, que identifican a un programa dentro de cada computadora.

Los sockets permiten implementar una arquitectura cliente-servidor. La comunicación debe ser iniciada por uno de los programas que se denomina programa "cliente". El segundo programa espera a que otro inicie la comunicación, por este motivo se denomina programa "servidor".

Un socket es un proceso o hilo existente en la máquina cliente y en la máquina servidora, que sirve en última instancia para que el programa servidor y el cliente lean y escriban la información. Esta información será la transmitida por las diferentes capas de red.

 

Conexión por socket en Visual Basic 6.0 y anteriores

Para las versiones de Visual Basic 6 y anteriores, si queríamos desarrollar una aplicación con conexión por socket debíamos usar el componente WinSock. Dicho componente se agregaba a Visual Basic 6 desde el menú "Proyecto" - "Componentes":

Conexión por socket en Visual Basic 6.0 y anteriores

En la pestaña "Controles" buscamos "Microsoft Winsock Control 6.0":

C:/Windows/system32/MSWINSCK.OCK

lo marcamos y pulsamos "Aceptar":

Conexión por socket en Visual Basic 6.0 y anteriores

Nos agregará un nuevo elemento a la paleta de componentes:

Conexión por socket en Visual Basic 6.0 y anteriores

 

Aplicación servidor para conexión por socket con Visual Basic 6

Mostramos a continuación un ejemplo de aplicación en Visual Basic 6 para conexión con Socket mediante Winsock, por un lado la aplicación servidor, que tendrá este aspecto:

Aplicación servidor para conexión por socket con Visual Basic 6

Una vez agregado el componente Winsock al formulario de nuestra aplicación servidor VB6 podremos programarlo, por ejemplo, para establecer el modo escucha de la que sería la aplicacion servidor, agregando un botón llamado "btEscuchar" con el siguiente código:

  Private Sub btEscuchar_Click()
    on error goto cError
    'Cerrar conexiones actuales
    Winsock1.Close
    'Puerto por el que escucharemos
    Winsock1.LocalPort = txtPuerto.Text
    'Activamos el modo escucha
    Winsock1.Listen
    'desplegamos un mensaje en la ventana
    txtLog.Text = txtLog.Text & _
        "Iniciado servidor, escuchando..." & vbCrLf
    btDesactivarEscucha.Enabled = True
    btEscuchar.Enabled = False
    txtMensaje.Enabled = True
    btEnviarMensaje.Enabled = True
:cSalir
  exit sub

:cError
  MsgBox "Error al activar servidor: " + err.number + vbcrlf + _
      " Descripción del error: " + err.description 	
  End Sub

El evento "ConnectionRequest" del componente WinSock se ejecutará cada vez que un cliente intente establecer una conexión con el servidor, podremos colocar el siguiente código:

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
  'Mostrar mensaje cuando un cliente se conecte
  txtLog.Text = txtLog.Text & _
      "Petición de conexión cliente " & requestID & vbCrLf
  'Cerrar el socket
  Winsock1.Close
  'Aceptar la conexión
  Winsock1.Accept requestID
  'desplegamos un mensaje en la ventana
  txtLog.Text = txtLog.Text & "Cliente conectado: "  & _
      requestID & vbCrLf
End Sub

Para desactivar el modo escucha y cerrar todas las conexiones actuales en el servidor agregaremos el botón "btDesactivarEscucha" con el siguiente código:

Private Sub btDesactivarEscucha_Click()
  'Cerrar conexión Socket
  Winsock1.Close  
End Sub

Cuando el usuario pulse en el botón "Desactivar escucha", se ejecutará el evento "Close" del WinSock, desde este evento podremos controlar cuando el servidor deja de escuchar clientes:

Private Sub Winsock1_Close()
  txtLog.Text = txtLog.Text & _
      "Desactivado modo escucha, no se aceptarán conexiones" & vbCrLf
  btDesactivarEscucha.Enabled = False
  btEscuchar.Enabled = True
  txtMensaje.Enabled = False
  btEnviarMensaje.Enabled = False
End Sub

Para agregar un botón al formulario del servidor que envíe un mensaje al cliente conectado (btEnviarMensaje) usaremos el siguiente código:

Private Sub btEnviarMensaje_Click()
  Winsock1.SendData txtMensaje.Text & vbCrLf
End Sub

Para mostrar los mensajes enviados por los clientes al servidor, usaremos el evento "DataArrival" del componente WinSock, este evento se ejecuta cada vez que se reciben datos de algún cliente conectado:


Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
  Dim datosRecibidos As String
  'Obtener los datos enviados por el cliente
  Winsock1.GetData datosRecibidos
  txtMensajesClientes.Text = txtMensajesClientes.Text & _
      "Mensaje: " & datosRecibidos
End Sub

Si se produce algún error podemos "controlarlo" con el evento "Error" del componente "WinSock", por ejemplo podríamos mostrar el error cuando se produzca y cerrar las conexiones:

Private Sub Winsock1_Error( _
    ByVal Number As Integer, Description As String, _
	ByVal Scode As Long, ByVal Source As String, _
	ByVal HelpFile As String, ByVal HelpContext As Long, _
	CancelDisplay As Boolean)
  'Si se produce un error cerramos la conexión
  Winsock1.Close
  'Mostramos el error
  MsgBox "Error con WinSock: " & Number & ": " & _
      Description, vbCritical
End Sub

Aplicación cliente para conexión por socket con Visual Basic 6

Para el caso de la aplicación cliente con VB6 y Winsock tendrá este aspecto:

Aplicación cliente para conexión por socket con Visual Basic 6

Para realizar una conexión del equipo cliente con el equipo servidor especificado en txtServidor y el puerto especifidaco en txtPuerto agregaremos el siguiente código para el botón"btConectar":

Private Sub btConectar_Click()
  'Asignamos la IP o hostname a Winsock
  Winsock1.RemoteHost = txtServidor.Text
  'Asignamos el puerto a Winsock
  Winsock1.RemotePort = txtPuerto.Text
  'Desconectamos por si acaso estaba conectado ya
  Winsock1.Close
  'Realizamos la conexión mediante Socket al servidor y puerto
  Winsock1.Connect
End Sub

Si la conexión se ha establecido con el equipo servidor de socket, se ejecutará el evento "Connect" de Winsock, en dicho evento podremos añadir el siguiente código:

Private Sub Winsock1_Connect()
  'desplegamos un mensaje en la ventana
  txtLog.Text = txtLog.Text & _
      "Conexión establecida con servidor " & _
	  txtServidor.Text & ":" & txtPuerto.Text & vbCrLf
End Sub

Otro evento que programaremos, cuando se pierde la conexión del cliente con el servidor, será el "Close" de Winsock, por ejemplo podremos añadir el siguiente código a este evento:

Private Sub Winsock1_Close()
  txtLog.Text = txtLog.Text & _
      "Desconectado de servidor" & vbCrLf
End Sub

En el botón "btDesconectar" colocaremos el siguiente código, con este botón el usuario podrá desconectarse del servidor cuando lo estime pertinente:

Private Sub btDesconectar_Click()
  'Cerramos la conexión con el servidor
  Winsock1.Close
End Sub

El botón para enviar un mensaje de texto al servidor "btEnviarMensaje" tendrá el siguiente código:

Private Sub btEnviar_Click()
  'Enviar txtMensaje a servidor
  Winsock1.SendData txtMensaje.Text & vbCrLf
End Sub

Si el servidor nos envía algún mensaje, lo podremos mostrar programando el evento DataArrival del componente Winsock, con el siguiente código VB6:

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
  Dim datosRecibidos As String
  'Se obtienen los datos enviados por el servidor
  Winsock1.GetData datosRecibidos
  txtMensajesServidor = txtMensajesServidor.Text & _
      "Servidor: " & datosRecibidos
End Sub

Si se produce algún error podemos "controlarlo" con el evento "Error" del componente "WinSock", por ejemplo podríamos mostrar el error cuando se produzca y cerrar las conexiones:


Private Sub Winsock1_Error( _
    ByVal Number As Integer, Description As String, _
	ByVal Scode As Long, ByVal Source As String, 
    ByVal HelpFile As String, ByVal HelpContext As Long, _
	CancelDisplay As Boolean)
  'Si se produce un error cerramos la conexión
  Winsock1.Close
  'Mostramos el error
  MsgBox "Error con WinSock: " & Number & ": " & _
      Description, vbCritical
End Sub

Con los ejemplos anteriores mostramos cómo se programaba con Visual Basic 6 y anteriores una aplicación cliente-servidor mediante conexión por Socket. Como se puede observar este ejemplo, con algunos retoques, puede servir para desarrollar una aplicación de Chat. Por supuesto este tipo de conexiones entre aplicaciones, que puede ser usada en una red LAN o incluso a través de internet abriendo los puertos correspondientes en los routers o cortafuegos, permite ser usada para múltiples propósitos como por ejemplo controlar una aplicación desde otra, incluso controlar un PC desde otro.

Tal y como lo hemos programado sólo se aceptará una conexión por cada servidor, para permitir múltiples conexiones habría que usar una matriz de componentes Winsock e ir creando uno nuevo por cada conexión que se establezca. No entraremos más en detalle sobre socket con VB6 por estar este lenguaje de programación obsoleto. A continuación pasaremos a explicar los socket con VB.Net.

 

Conexión por socket en Visual Basic .Net de Visual Studio 2010

A partir de Microsoft Visual Studio .Net, Microsoft incorporó un Namespace para trabajar con Socket: System.Net.Sockets, será este Namespace el que usemos para realizar una aplicación de ejemplo que utilice Socket para conectar dos PCs a través de Internet o de la red LAN y enviar mensajes de texto (o incluso enviar ficheros) entre uno y otro.

Sin duda el namespace System.Net.Sockets es mucho más "potente" que el antiguo Winsock, proporciona más funciones, propiedades, eventos y métodos y más eficientes. Aunque echamos de menos que todo esto no esté implementando en un componente, lo cual facilitaría bastante las cosas, como ocurre con la antigua versión de Borland Delphi 6, que incluía un componente para Socket con todas las opciones para una sencilla programación. Por ejemplo la aplicación de AjpdSoft Chat, bastante profesional, ha sido desarrollada con Delphi 6 y estos componentes (ClientSocket y ServerSocket):

AjpdSoft Chat UDP código fuente en Delphi

También AjpdSoft Aviso cambio IP pública usa socket para conexión entre el usuario y el servidor donde se guardan las IPs. O la aplicación AjpdSoft Transferencia de ficheros que envía ficheros entre PCs mediante socket.

Volviendo a Microsoft Visual Studio .Net, utilizaremos Visual Basic .Net VB.Net para conectar dos equipos mediante Socket. A continuación explicaremos cómo desarrollar la aplicación servidor y la aplicación cliente. Veremos que es un poco "arduo" debido a que no incorpora un componente para este menester.

 

Aplicación servidor para conexión por socket con Visual Basic .Net

En la aplicación servidor agregaremos los siguientes componentes:

Aplicación servidor para conexión por socket con Visual Basic .Net

Agregaremos una clase a nuestro proyecto AjpdSoftSocketServidor, en esta clase que llamaremos "ClaseServidorSocket" agregaremos el código necesario para interactuar con el Namespace System.Net.Sockets:

Imports System.Threading
Imports System.Net.Sockets
Imports System.Text


Public Class ClaseServidorSocket

    'Esta estructura permite guardar la información sobre un cliente
    Private Structure datosClienteConectado
        Public socketConexion As Socket 'Socket para mantener la conexión con cliente
        Public Thread As Thread 'Hilo para mantener escucha con el cliente
        Public UltimosDatosRecibidos As String 'Últimos datos enviados por el cliente
    End Structure

    Private tcpLsn As TcpListener 'Para realizar la escuchas de conexiones de clientes
    Private Clientes As New Hashtable() 'Datos de los clientes conectados
    Private tcpThd As Thread
    Private IDClienteActual As Net.IPEndPoint 'Último cliente conectado
    Private m_PuertoDeEscucha As String

    Public Event NuevaConexion(ByVal IDTerminal As Net.IPEndPoint)
    Public Event DatosRecibidos(ByVal IDTerminal As Net.IPEndPoint)
    Public Event ConexionTerminada(ByVal IDTerminal As Net.IPEndPoint)

    'Propiedad para establecer el puerto por el que se realizará la escucha
    Property Puerto() As Integer
        Get
            Puerto = m_PuertoDeEscucha
        End Get

        Set(ByVal Value As Integer)
            m_PuertoDeEscucha = Value
        End Set
    End Property

    'Procedimiento para establecer el servidor en modo escucha
    Public Sub IniciarEscucha()
        tcpLsn = New TcpListener(Puerto)

        'Iniciar escucha
        tcpLsn.Start()

        'Crear hilo para dejar escuchando la conexión de clientes
        tcpThd = New Thread(AddressOf EsperarConexionCliente)
        tcpThd.Start()
    End Sub


    'Procedimiento para detener la escucha del servidor
    Public Sub DetenerEscucha()
        CerrarTodosClientes()
        tcpThd.Abort()
        tcpLsn.Stop()
    End Sub


    Public Function ObtenerDatos(ByVal IDCliente As Net.IPEndPoint) As String
        Dim InfoClienteSolicitado As datosClienteConectado

        'Obtengo la informacion del cliente solicitado
        InfoClienteSolicitado = Clientes(IDCliente)
        ObtenerDatos = InfoClienteSolicitado.UltimosDatosRecibidos
    End Function

    'Cierra la conexión de un cliente conectado
    Public Sub cerrarConexionCliente(ByVal IDCliente As Net.IPEndPoint)
        Dim InfoClienteActual As datosClienteConectado

        'Obtener información del cliente indicado
        InfoClienteActual = Clientes(IDCliente)

        'Cerrar conexión con cliente
        InfoClienteActual.socketConexion.Close()
    End Sub


    'Cerrar todas la conexión de todos los clientes conectados
    Public Sub CerrarTodosClientes()
        Dim InfoClienteActual As datosClienteConectado

        'Cerrar conexión de todos los clientes
        For Each InfoClienteActual In Clientes.Values
            Call cerrarConexionCliente(InfoClienteActual.socketConexion.RemoteEndPoint)
        Next
    End Sub

    'Enviar mensaje a cliente indicado
    Public Sub enviarMensajeCliente(ByVal IDCliente As Net.IPEndPoint, _
            ByVal Datos As String)
        Dim Cliente As datosClienteConectado

        'Obtener información del cliente al que se enviará el mensaje
        Cliente = Clientes(IDCliente)

        'Enviar mensaje a cliente
        Cliente.socketConexion.Send(Encoding.ASCII.GetBytes(Datos))
    End Sub

    'Enviar mensaje a todos los clientes conectados al servidor
    Public Sub enviarMensajeTodosClientes(ByVal Datos As String)
        Dim Cliente As datosClienteConectado

        For Each Cliente In Clientes.Values
            enviarMensajeCliente(Cliente.socketConexion.RemoteEndPoint, Datos)
        Next
    End Sub

    'Procedimiento que inicia la espera de la conexión de un cliente
    'para ello inicia un hilo (thread)
    Private Sub EsperarConexionCliente()
        Dim datosClienteActual As datosClienteConectado

        While True
            'Se guarda la información del cliente cuando se recibe la conexión
            'Quedará esperando la conexión de un nuevo cliente
            datosClienteActual.socketConexion = tcpLsn.AcceptSocket()

            'Con el IDClienteActual se identificará al cliente conectado
            IDClienteActual = datosClienteActual.socketConexion.RemoteEndPoint

            'Crear un hilo para que quede escuchando los mensajes del cliente
            datosClienteActual.Thread = New Thread(AddressOf LeerSocket)

            'Agregar la información del cliente conectado al array
            SyncLock Me
                Clientes.Add(IDClienteActual, datosClienteActual)
            End SyncLock

            'Generar evento NuevaConexion
            RaiseEvent NuevaConexion(IDClienteActual)

            'Iniciar el hilo que escuchará los mensajes del cliente
            datosClienteActual.Thread.Start()
        End While
    End Sub

    'Procedimiento para leer datos enviados por el cliente
    Private Sub LeerSocket()
        Dim IDReal As Net.IPEndPoint 'ID del cliente que se va a escuchar
        Dim Recibir() As Byte 'Array donde se guardarán los datos que lleguen
        Dim InfoClienteActual As datosClienteConectado 'Datos del cliente conectado
        Dim Ret As Integer = 0

        IDReal = IDClienteActual
        InfoClienteActual = Clientes(IDReal)


        While True
            If InfoClienteActual.socketConexion.Connected Then
                Recibir = New Byte(100) {}
                Try
                    'Esperar a que lleguen un mensaje desde el cliente
                    Ret = InfoClienteActual.socketConexion.Receive(Recibir,
                             Recibir.Length, SocketFlags.None)
                    If Ret > 0 Then
                        'Guardar mensaje recibido
                        InfoClienteActual.UltimosDatosRecibidos =
                            Encoding.ASCII.GetString(Recibir)
                        Clientes(IDReal) = InfoClienteActual

                        'Generar el evento DatosRecibidos 
                        'para los datos recibidos
                        RaiseEvent DatosRecibidos(IDReal)
                    Else
                        'Generar el evento ConexionTerminada 
                        'de finalización de la conexión
                        RaiseEvent ConexionTerminada(IDReal)
                        Exit While
                    End If
                Catch e As Exception
                    If Not InfoClienteActual.socketConexion.Connected Then
                        'Generar el evento ConexionTerminada 
                        'de finalización de la conexión
                        RaiseEvent ConexionTerminada(IDReal)
                        Exit While
                    End If
                End Try
            End If
        End While
        Call CerrarThread(IDReal)
    End Sub

    'Procedimiento para cerrar el hilo (thread)
    Private Sub CerrarThread(ByVal IDCliente As Net.IPEndPoint)
        Dim InfoClienteActual As datosClienteConectado

        'Finalizar el hilo (thread) iniciado 
        ' encargado de escuchar al cliente
        InfoClienteActual = Clientes(IDCliente)

        Try
            InfoClienteActual.Thread.Abort()
        Catch e As Exception
            SyncLock Me
                'Eliminar el cliente del array
                Clientes.Remove(IDCliente)
            End SyncLock
        End Try
    End Sub
End Class

A continuación mostramos el código completo para el formulario de la aplicación AjpdSoft Socket VB.Net Servidor, en el código incluimos los eventos necesarios, el botón "Escuchar", el botón "Detener escucha" y el botón "Enviar datos":

Public Class formSocketServidor

    Dim WithEvents socketServidor As New ClaseServidorSocket()

    'Iniciar el servidor, establecer el modo escucha
    'para recibir conexión de clientes
    Private Sub btEscuchar_Click(sender As System.Object,
               e As System.EventArgs) Handles btEscuchar.Click
        If txtPuerto.Text <> "" Then
            Try
                socketServidor.Puerto = txtPuerto.Text
                socketServidor.IniciarEscucha()
                btEscuchar.Enabled = False
                txtPuerto.Enabled = False
                txtMensaje.Enabled = True
                btEnviarMensaje.Enabled = True
                btDetenerEscucha.Enabled = True
                txtMensaje.Focus()
            Catch err As Exception
                MsgBox("Se ha producido un error al intentar " & _
                       "establecer escucha por el puerto " & _
                   txtPuerto.Text & vbCrLf & vbCrLf & err.Message,
                   MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)
            End Try
        Else
            MsgBox("Debe indicar el puerto por el que establecer la escucha.",
                    MsgBoxStyle.Information + MsgBoxStyle.OkOnly)
            txtPuerto.Focus()
        End If
    End Sub


    'Evento que se ejecutará cuando un nuevo cliente se conecte
    Private Sub socketServidor_NuevaConexion(ByVal IDTerminal As  _
                 System.Net.IPEndPoint) Handles socketServidor.NuevaConexion
        txtLog.Text = txtLog.Text & vbCrLf & "Conectado cliente: " &
            IDTerminal.Address.ToString & ", Puerto: " & IDTerminal.Port
    End Sub


    'Evento que se ejecutará cuando finalice la conexión de un cliente
    Private Sub socketServidor_ConexionTerminada(ByVal IDTerminal As  _
                 System.Net.IPEndPoint) Handles socketServidor.ConexionTerminada
        txtLog.Text = txtLog.Text & vbCrLf & "Desconectado cliente: " &
            IDTerminal.Address.ToString & ", Puerto: " & IDTerminal.Port
        btEscuchar.Enabled = True
        txtPuerto.Enabled = True
    End Sub

    'Evento que se ejecutará cuando se reciban datos de los clientes conectados
    Private Sub socketServidor_DatosRecibidos(ByVal IDTerminal As  _
               System.Net.IPEndPoint) Handles socketServidor.DatosRecibidos
        'Datos del cliente que se conecta
        txtLog.Text = txtLog.Text & vbCrLf &
            "Cliente: " & IDTerminal.Address.ToString &
            ", Puerto: " & IDTerminal.Port

        'Mensaje recibido del cliente
        txtMensajeRecibido.Text = IDTerminal.Address.ToString & " " & Now & " " &
            txtMensajeRecibido.Text & " " & socketServidor.ObtenerDatos(IDTerminal)
    End Sub

    'Enviar mensaje a todos los clientes conectados
    Private Sub btEnviarMensaje_Click(sender As System.Object,
              e As System.EventArgs) Handles btEnviarMensaje.Click
        socketServidor.enviarMensajeTodosClientes(txtMensaje.Text)
    End Sub

    'Detener modo escucha, no se recibirán conexiones de clientes
    Private Sub btDetenerEscucha_Click(sender As System.Object,
              e As System.EventArgs) Handles btDetenerEscucha.Click
        btEscuchar.Enabled = True
        txtPuerto.Enabled = True
        txtMensaje.Enabled = False
        btEnviarMensaje.Enabled = False
        btDetenerEscucha.Enabled = False
        Try
            socketServidor.DetenerEscucha()
        Catch err As Exception
            MsgBox("Error al detener la escucha:" + vbCrLf +
                   vbCrLf + err.Message,
                   MsgBoxStyle.Information + MsgBoxStyle.OkOnly)
        End Try
    End Sub

    'Finalizamos con End para cerrar el hilo (thread) abierto 
    Private Sub formSocketServidor_FormClosed(sender As System.Object,
               e As System.Windows.Forms.FormClosedEventArgs) _
               Handles MyBase.FormClosed
        End
    End Sub
End Class

Aplicación cliente para conexión por socket con Visual Basic .Net

En la aplicación cliente agregaremos los siguientes componentes:

Aplicación cliente para conexión por socket con Visual Basic .Net

Agregaremos una clase a nuestro proyecto AjpdSoftSocketCliente, en esta clase que llamaremos "ClaseClienteSocket" agregaremos el código necesario para interactuar con el Namespace System.Net.Sockets:

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


Public Class ClaseClienteSocket

    Private mensajesEnviarRecibir As Stream 'Para enviar y recibir datos del servidor
    Private ipServidor As String 'Dirección IP
    Private puertoServidor As String 'Puerto de escucha

    Private clienteTCP As TcpClient
    Private hiloMensajeServidor As Thread 'Escuchar mensajes enviados desde el servidor


    Public Event ConexionTerminada()
    Public Event DatosRecibidos(ByVal datos As String)

    'Dirección IP del servidor al que nos conectaremos
    Public Property IP() As String
        Get
            IP = ipServidor
        End Get

        Set(ByVal Value As String)
            ipServidor = Value
        End Set
    End Property

    'Puerto por el que realizar la conexión al servidor
    Public Property Puerto() As Integer
        Get
            Puerto = puertoServidor
        End Get

        Set(ByVal Value As Integer)
            puertoServidor = Value
        End Set
    End Property

    'Procedimiento para realizar la conexión con el servidor
    Public Sub Conectar()
        clienteTCP = New TcpClient()

        'Conectar con el servidor
        clienteTCP.Connect(IP, Puerto)
        mensajesEnviarRecibir = clienteTCP.GetStream()

        'Crear hilo para establecer escucha de posibles mensajes
        'enviados por el servidor al cliente
        hiloMensajeServidor = New Thread(AddressOf LeerSocket)
        hiloMensajeServidor.Start()
    End Sub

    'Procedimiento para cerrar la conexión con el servidor
    Public Sub Desconectar()
        'desconectamos del servidor
        clienteTCP.Close()
        'abortamos el hilo (thread)
        hiloMensajeServidor.Abort()
    End Sub


    'Enviar mensaje al servidor
    Public Sub EnviarDatos(ByVal Datos As String)
        Dim BufferDeEscritura() As Byte

        BufferDeEscritura = Encoding.ASCII.GetBytes(Datos)
        If Not (mensajesEnviarRecibir Is Nothing) Then
            mensajesEnviarRecibir.Write(BufferDeEscritura,
                    0, BufferDeEscritura.Length)
        End If
    End Sub


    Private Sub LeerSocket()
        Dim BufferDeLectura() As Byte

        While True
            Try
                BufferDeLectura = New Byte(100) {}

                'Esperar a que llegue algún mensaje
                mensajesEnviarRecibir.Read(BufferDeLectura,
                      0, BufferDeLectura.Length)

                'Generar evento DatosRecibidos cuando se recibien datos desde el servidor
                RaiseEvent DatosRecibidos(Encoding.ASCII.GetString(BufferDeLectura))
            Catch e As Exception
                Exit While
            End Try
        End While

        'Finalizar conexión y generar evento ConexionTerminada
        RaiseEvent ConexionTerminada()
    End Sub
End Class

A continuación mostramos el código completo para el formulario de la aplicación AjpdSoft Socket VB.Net Servidor, en el código incluimos los eventos necesarios, el botón "Escuchar", el botón "Detener escucha" y el botón "Enviar datos":

Public Class formSocketCliente

    Dim WithEvents socketCliente As New ClaseClienteSocket

    Private Sub btEnviar_Click(sender As System.Object,
             e As System.EventArgs) Handles btEnviar.Click
        Try
            'Enviar mensaje al servidor
            socketCliente.EnviarDatos(txtMensaje.Text)
        Catch err As Exception
            MsgBox("Error al enviar mensaje al servidor." &
                   vbCrLf & vbCrLf & err.Message)
        End Try
    End Sub

    'Evento que se ejecuta cuando se reciben datos
    Private Sub socketCliente_DatosRecibidos( _
            ByVal datos As String) Handles socketCliente.DatosRecibidos
        bePanel2.Text = "Recibidos datos del servidor"
        txtMensajeRecibido.Text = Now + " Servidor: " & datos
    End Sub

    Private Sub socketCliente_ConexionTerminada() Handles _
            socketCliente.ConexionTerminada
        bePanel2.Text = "Conexión finalizada"
        txtServidor.Enabled = True
        txtPuerto.Enabled = True
        btConectar.Enabled = True
        btDesconectar.Enabled = False
        btEnviar.Enabled = False
        txtListaMensajes.Enabled = False
        bePanel1.Text = "No conectado"
        txtServidor.Focus()
    End Sub

    Private Sub btConectar_Click(sender As System.Object,
            e As System.EventArgs) Handles btConectar.Click
        'Conexión del cliente con el servidor (IP ó hostname y puerto)
        If txtServidor.Text = "" Or txtPuerto.Text = "" Then
            MsgBox("Debe indicar el servidor (IP o hostname) y " _
                   & "el puerto al que realizar la conexión.",
                   MsgBoxStyle.Information + MsgBoxStyle.OkOnly)
            txtServidor.Focus()
        Else
            Try
                socketCliente.IP = txtServidor.Text
                socketCliente.Puerto = CInt(txtPuerto.Text)

                socketCliente.Conectar()

                txtServidor.Enabled = False
                txtPuerto.Enabled = False
                btConectar.Enabled = False
                btEnviar.Enabled = True
                txtMensaje.Enabled = True
                btDesconectar.Enabled = True
                bePanel1.Text = "Conectado"
                bePanel1.Text = "Conexión establecida a " & _
                    txtServidor.Text & ":" & txtPuerto.Text
            Catch err As Exception
                bePanel1.Text = "No conectado"
                MsgBox("Error al conectar al servidor " & txtServidor.Text &
                       vbCrLf & vbCrLf & err.Message,
                       MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)
            End Try
        End If
    End Sub

    Private Sub formSocketCliente_FormClosed(sender As System.Object,
             e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
        End
    End Sub

    Private Sub btDesconectar_Click(sender As System.Object, _
            e As System.EventArgs) Handles btDesconectar.Click
        txtServidor.Enabled = True
        txtPuerto.Enabled = True
        btConectar.Enabled = True
        btEnviar.Enabled = False
        txtMensaje.Enabled = False
        btDesconectar.Enabled = False
        Try
            socketCliente.Desconectar()
        Catch err As Exception
            MsgBox("Error al desconectar del servidor " & txtServidor.Text &
                 vbCrLf & vbCrLf & err.Message,
                 MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)
        End Try
    End Sub
End Class

AjpdSoft Socket VB.Net en funcionamiento

A continuación mostramos cómo funciona la aplicación a AjpdSoft Socket VB.Net, por un lado iniciaremos la parte Servidor, introduciremos el puerto a usar para las conexiones (debe estar libre), en nuestro caso usaremos el 1010 y pulsaremos "Escuchar":

AjpdSoft Socket VB.Net en funcionamiento

La aplicación Servidor quedará en modo escucha, esperando la conexión de los clientes, si el puerto está usado ya por otra aplicación mostrará un error, si el puerto está libre activará el botón "Enviar a todos":

AjpdSoft Socket VB.Net en funcionamiento

Iniciaremos la aplicación Cliente, en esta aplicación deberemos indicar la IP o nombre de red (hostname) del equipo que tiene la aplicación Servidor, incluso podremos establecer la conexión a través de Internet si hemos redireccionado correctamente el puerto usado en el router o cortafuegos. En nuestro caso usaremos la IP 127.0.0.1 debido a que la aplicación Servidor y Cliente están en el mismo equipo. Introduciremos el mismo puerto con el que hemos activado la escucha en el Server, el 1010 y pulsaremos "Conectar":

AjpdSoft Socket VB.Net en funcionamiento

Si todo es correcto y el Servidor recibe la conexión, la aplicación Servidor mostrará "Conectado cliente ...":

AjpdSoft Socket VB.Net en funcionamiento

Para enviar un mensaje al Servidor lo escribiremos en "Mensaje" y pulsaremos "Enviar":

AjpdSoft Socket VB.Net en funcionamiento

En el Servidor se habrá recibido el mensaje enviado por el Cliente, si queremos enviar un mensaje del servidor a todos los clientes conectados lo escribiremos y pulsaremos en "Enviar a todos":

AjpdSoft Socket VB.Net en funcionamiento

Los clientes conectados recibirán el mensaje enviado desde el Servidor:

AjpdSoft Socket VB.Net en funcionamiento

 

Artículos relacionados

  

Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.

Artículo en inglés.


Anuncios


Enviado el Domingo, 23 octubre a las 23:26:01 por ajpdsoft
Este sitio web NO CONTIENE malware, todos los programas con código fuente aquí. Autor: Alonso Javier Pérez Díaz Google+ Síguenos en Google+