Monografias.com > Computación > Programación
Descargar Imprimir Comentar Ver trabajos relacionados

Tutorial de cliente/servidor en Visual Basic 6.0




Enviado por Gemu



    1. ¿Qué es
      cliente/servidor?
    2. Preparando el Visual
      Basic
    3. Descripción del componente
      Winsock
    4. Mi primera aplicación
      cliente
    5. Mi primera
      aplicación servidor
    6. Aplicación servidor
      multi-conexión
    7. Conclusión

    INTRODUCCION

    Este tutorial pretende explicar en forma práctica
    la implementación y desarrollo de
    aplicaciones cliente y servidor, ya sea mono-conexión o
    multi-conexiones, usando el componente Winsock Control 6.0 sobre
    el entorno de desarrollo de VisualBasic v6.0. Cualquier otra
    versión de este control debería funcionar
    también.

    Para el seguimiento de este texto, se
    recomienda ir practicando las cosas mencionadas a la vez que las
    vallas leyendo, así podrás familiarizarte de mejor
    manera con el entorno y no te perderás por el
    camino.

    Se da por entendido que el lector conoce el lenguaje
    Visual Basic y
    este familiarizado con su sintaxis y metodología de programación.

    ¿QUE ES
    CLIENTE/SERVIDOR?

    Imagino que esta es la primera pregunta que se
    harán todos, ¿que es eso de cliente servidor?,
    cliente/servidor no es más que la forma de llamar a las
    aplicaciones que trabajan en conjunto como "nodos" de información (por así decirlo). Esto
    es que existe una aplicación totalmente independiente de
    la parte cliente la cual esta dispuesta a servir
    información cuando el cliente se la
    solicita.

    Ejemplos de estos pueden ser los servidores de
    Paginas Webs (HTTP), servidores
    de Transferencia de Archivos
    (FTP),
    etc.

    No podemos continuar sin antes dar una breve
    definición de los términos Cliente y
    Servidor.

    Cliente: Es toda aplicación que
    se conecta a un Servidor para solicitarle alguna
    información.

    Servidor: Es toda aplicación que se
    mantiene a la espera de un cliente que solicite
    información, la cual se la entregara si fuese posible. Se
    dice que este ofrece o sirve un servicio.

    Para que quede mas claro, voy a dar un ejemplo sobre el
    funcionamiento del servidor de Paginas Webs (HTTP). Para ello
    realizaremos una visita a un sitio Web en particular
    y analizaremos después lo sucedido:

    1. Ejecutamos nuestro navegador (Internet
      Explorer, Netscape, Firefox, etc.)
    2. Ingresamos la dirección del sitio Web que deseamos ver,
      por ej. www.google.com
    3. Le damos al botón "Ir", "Ver", etc. Para que
      nuestro navegador se conecte a la dirección.
    4. Nuestro navegador inmediatamente comienza a recibir
      poco a poco la página
      Web solicitada.
    5. Una vez concluida la descarga nuestro navegador se
      desconecta del sitio de forma oculta al usuario.

    Ahora si analizamos los pasos que fueron necesarios para
    visitar un sitio Web, veremos que lo primero que tenemos que
    hacer es ejecutar un programa específico el cual
    tiene la habilidad de conectarse a una dirección Web. Este
    programa que
    se conecta a X dirección, lo llamaremos Cliente,
    porque es el que solicita la información, en este caso
    solicita una pagina Web. Y quien le entrega dicha
    información al cliente se llamara Servidor, que en
    este caso es una aplicación que corre bajo la
    dirección del sitio en un computador
    remoto conectado a Internet (www.google.com).

    Como conclusión, si analizamos la petición
    de la página Web podemos obtener que los elementos
    básicos que necesitamos para una conexión
    cliente/servidor son:

    • Un programa Cliente (el que solicita la
      información)
    • Un programa Servidor (el que sirve la
      información que necesitamos)
    • Una dirección hacia el servidor (para poder saber
      a donde conectar)

    Con estos tres elementos podemos realizar una
    conexión cliente/servidor sin problemas y es
    la base de las aplicaciones.

    También es muy importante mencionar, que en lo
    que a "dirección" se refiere, esta formada por un
    número IP (o DNS) y un
    número de PUERTO. Este último es así porque
    un computador puede tener muchos puertos destinados para ofrecer
    distintos servicios, ya
    sean Paginas Webs (Puerto 80), Mails (Puerto 25 y 110), FTP
    (puerto 21), Telnet (23),
    etc.

    Estos puertos que he mencionado son los acostumbrados
    para estos servicios, eso no quiere decir que tenga que ser
    siempre así, por ej. Podemos usar el puerto 80
    (Comúnmente para HTTP) para ofrecer un servicio FTP, o
    bien implementar un Chat o
    cualquier cosa que se nos ocurra. Los puertos solo están
    disponibles para cualquier uso que le queramos dar.

    Como referencia es bueno saber cuantos puertos puede
    usar una computadora.
    Los puertos están direccionados por 16 Bits, esto es que
    existe un total de 2^16 puertos, lo que equivale a 65.536 puertos
    disponibles, aunque como el puerto 0 no se puede usar solo
    tenemos utilizables desde el puerto 1 al puerto
    65.535.

    PREPARANDO EL
    VISUAL BASIC

    El Visual Basic v6.0 por defecto no esta preparado para
    trabajar con aplicaciones cliente/servidor, y hace falta acomodar
    algunas cosas antes de comenzar a trabajar.

    1. Lo primero será crear un nuevo proyecto. Elige
      Aplicación Estándar (prácticamente puede
      ser cualquier otra, pero en este caso se trabajara
      así)
      1. Ve al menú "Proyecto" y selecciona
        "Componentes".
      2. En la lista de componentes busca "Microsoft Winsock Control 6.0", puede ser
        otra versión o bien terminar con
        "(SP6)".
      3. Marca este control y dale al botón
        "Aceptar".
    2. Ahora necesitaremos cargar el Control Winsock, para
      ello realiza lo sig.:

    Con esto veremos que se nos agrega un nuevo control
    llamado Winsock, con el icono .

    Ahora ya nos encontramos listos para realizar una
    aplicación Cliente/Servidor.

    DESCRIPCION DEL
    COMPONENTE WINSOCK

    El componente Winsock del Visual Basic es el que permite
    realizar conexiones Cliente/Servidor a través de protocolos TCP y
    UDP. Este único componente puede trabajar de dos formas,
    como Cliente (Conecta a un servidor) y como Servidor (Recibe
    conexiones), además de poder realizar vectores de
    Winsock lo que permite administrar varias conexiones con un mismo
    código
    en común.

    Este componente depende directamente del control ActiveX
    MSWINSCK.OCX.

    A continuación paso a describir las principales
    propiedades, métodos y
    eventos del
    componente.

    Propiedades

    Property BytesReceived As Long
    (Solo lectura)

    Retorna el número de Bytes
    recibidos en la conexión.

    Property Index As Integer (Solo
    lectura)

    Retorna/Asigna el numero que identifica
    al control en un arreglo de controles.

    Property LocalHostName As String
    (Solo lectura)

    Retorna el nombre de la maquina
    local.

    Property LocalIP As String (Solo
    lectura)

    Retorna la dirección IP de la
    maquina local.

    Property LocalPort As Long (Solo
    lectura)

    Retorna el puerto usado en la maquina
    local.

    Property Protocol As
    ProtocolConstants

    Retorna/Asigna el tipo de protocolo que
    usara el Socket

    Estos valores pueden
    ser dos: sckTCPProtocol y sckUDPProtocol.

    Property RemoteHost As
    String

    Retorna/Asigna el nombre
    (dirección) usado para identificar a la maquina
    remota.

    Property RemoteHostIP As String
    (Solo lectura)

    Retorna la dirección IP del Host
    Remoto.

    Property RemotePort As
    Long

    Retorna/Asigna el puerto al cual se
    conectara en el computador remoto.

    Property SocketHandle As Long
    (Solo lectura)

    Retorna el manejador (Handle) del
    Socket. (Solo para usuarios avanzados)

    Property State As Integer (Solo
    lectura)

    Retorna el estado de
    la conexion del Socket.

    Metodos

    Sub Accept(requestID As
    Long)

    Acepta un petición de
    conexión entrante.

    Sub Bind([LocalPort],
    [LocalIP])

    Amarra un socket a un específico
    puerto y adaptador.

    Sub Close()

    Cierra la conexión
    actual.

    Sub Connect([RemoteHost],
    [RemotePort])

    Conecta a un computador
    remoto.

    Sub GetData(data, [type],
    [maxLen])

    Recibe datos enviados
    por el computador remoto.

    Sub Listen()

    Se pone a la escucha de peticiones de
    conexión entrantes.

    Sub PeekData(data, [type],
    [maxLen])

    Mira los datos entrantes sin removerlos
    desde el buffer.

    Sub SendData(data)

    Envía datos al computador
    remoto.

    Eventos

    Event Close()

    Ocurre cuando la conexión a sido cerrada
    remotamente.

    Event Connect()

    Ocurre cuando la operación de conexión se
    ha completo.

    Event ConnectionRequest(requestID
    As Long)

    Ocurre cuando un cliente remoto se intenta
    conectar.

    Event DataArrival(bytesTotal As
    Long)

    Ocurre cuando se reciben datos desde un computador
    remoto.

    Event Error(Number As Integer,
    Description As String, Scode As Long, Source As String, HelpFile
    As String, HelpContext As Long, CancelDisplay As
    Boolean)

    Se dispara cuando ocurre algún error.

    Event SendComplete()

    Ocurre después que una operación de envio
    se haya completado.

    Event SendProgress(bytesSent As
    Long, bytesRemaining As Long)

    Ocurre mientras se esta enviando un dato.

    Constantes

    Enum StateConstants

    Estas son las constantes devueltas por la propiedad
    State.

    Constante

    Descripción

    sckClosed

    El socket se encuentra cerrado.

    sckClosing

    El socket esta cerrando la conexión al
    computador remoto.

    sckConnected

    El socket ha conectado al computador
    remoto.

    sckConnecting

    El socket esta conectando al computador
    remoto.

    sckConnectionPending

    El socket tiene una petición
    pendiente

    sckError

    Se ha producido un error

    sckHostResolved

    El socket ha resuelto el nombre del equipo
    remoto.

    sckListening

    El socket esta a la escucha de peticiones
    entrantes.

    sckOpen

    El socket esta actualmente abierto.

    sckResolvingHost

    El socket esta resolviendo el nombre del
    computador remoto.

    Enum ProtocolConstants

    Estos son los valores
    permitidos por la propiedad Protocol.

    Constante

    Descripción

    sckTCPProtocol

    Protocolo TCP.

    sckUDPProtocol

    Protocolo UDP.

    Enum ErrorConstants

    Constantes de errores, devueltas por el evento
    Error.

    Constante

    Descripción

    sckAddressInUse

    Dirección en uso.

    sckAddressNotAvailable

    La dirección no esta disponible desde la
    maquina local.

    sckAlreadyComplete

    La operación esta completa. En progreso
    la operación de no bloqueo.

    sckAlreadyConnected

    El socket esta actualmente conectado.

    sckBadState

    Protocolo o estado
    de conexión equivocada para la transacción
    o petición demandada.

    sckConnectAborted

    La conexión es abortada debido a que se
    ha superado el tiempo
    de conexión u otra falla.

    sckConnectionRefused

    La conexión a sido rechazada.

    sckConnectionReset

    La conexión a sido reinicializada por el
    lado remoto.

    sckGetNotSupported

    La propiedad es de Escritura solamente.

    sckHostNotFound

    Respuesta autorizada. No se ha encontrado el
    Host.

    sckHostNotFoundTryAgain

    Respuesta no autorizada. No se ha encontrado el
    Host.

    sckInProgress

    Una operación winsock de bloqueo esta en
    progreso.

    sckInvalidArg

    El argumento pasado a la función no posee un formato o rango
    valido.

    sckInvalidArgument

    Argumento invalido

    sckInvalidOp

    Operación invalida en el estado
    actual.

    sckInvalidPropertyValue

    Valor de propiedad invalido.

    sckMsgTooBig

    El datagrama es muy largo para acomodarlo dentro
    del buffer y ha sido truncado.

    sckNetReset

    Ha finalizado el tiempo de conexión
    cuando SO_KEEPALIVE estaba seteado.

    sckNetworkSubsystemFailed

    Falla en el subsistema de red.

    sckNetworkUnreachable

    La red no puede ser alcanzada desde este
    host.

    sckNoBufferSpace

    No hay espacio disponible en el
    buffer,

    sckNoData

    Nombre valido. No hay tipo de datos del registro demandado.

    sckNonRecoverableError

    Error irrecuperable.

    sckNotConnected

    El socket no esta conectado.

    sckNotInitialized

    WinsockInit debe ser llamado primero.

    sckNotSocket

    El descriptor no es un socket.

    sckOpCanceled

    Esta operación es cancelada.

    sckOutOfMemory

    La memoria se ha colapsado.

    sckOutOfRange

    El argumento esta fuera de rango.

    sckPortNotSupported

    El puerto especificado no esta
    soportado.

    sckSetNotSupported

    La propiedad es de solo lectura.

    sckSocketShutdown

    El socket había sido cerrado.

    sckSucces

    Concluido.

    sckTimedout

    Tiempo fuera en el intento de
    conexión.

    sckUnsupported

    No soporta tipos Variants.

    sckWouldBlock

    El socket no esta bloqueando y la especifica
    operación será realizada.

    sckWrongProtocol

    Protocolo equivocado para la especifica
    transacción o petición.

    MI PRIMERA
    APLICACIÓN CLIENTE

    Esta aplicación trabajara como un cliente simple
    que conecte a cualquier servidor, permita enviar texto plano y a
    la vez mostrar la información devuelta por este. Parecido
    a como trabajan los clientes de
    Telnet.

    1. Creando la interfaz del usuario

    Realiza un formulario como el mostrado abajo, con los
    nombres por defecto de cada control y guarda el proyecto con el
    nombre "Cliente.vbp".

    2. Implementando la conexión

    La primera acción
    a realizar y fundamental para toda aplicación de este
    tipo, es crear la conexión al servidor, ya que solo se
    puede transmitir información si la conexión
    cliente/servidor se encuentra activa.

    Propiedades necesarias

    – RemoteHost: Asignamos la dirección a la que
    deseamos conectar.

    – RemotePort: Asignamos el puerto al que deseamos
    conectar en RemoteHost.

    Métodos necesarios

    – Connect(): Conecta al servidor.

    – Close(): Cierra la conexión al
    servidor.

    Eventos involucrados

    – Connect(): Ocurre cuando hemos establecido con
    éxito
    la conexión al servidor

    – Close(): Ocurre cuando el servidor nos cierra la
    conexión.

    – Error(): Ocurre en caso de errores.

    Para realizar la conexión utilizamos el siguiente
    código:

    Private Sub
    Command2_Click()

    'asignamos los datos de
    conexion

    Winsock1.RemoteHost = Text3.Text

    Winsock1.RemotePort = Text4.Text

    'conectamos el socket

    Winsock1.Close

    Winsock1.Connect

    End Sub

    Aquí se pueden ver claramente dos partes
    principales:

    En las primeras dos líneas asignamos los datos de
    conexión al host remoto, como son la IP/DNS (RemoteHost) y
    Puerto (RemotePort).

    En la última línea llamamos al método
    "Connect" para realizar la conexión, siempre
    asegurándonos que el Socket no este utilizándose.
    Para ello llamamos al método "Close" que se encarga de
    cerrar toda conexión pendiente en el Socket.

    Nota: También se puede especificar los datos
    de conexión (IP y Puerto) directamente en el comando
    "Connect" como parámetros, de la sig. Forma:
    Winsock1.Connect(Host, Puerto).

    Si la conexión se realiza con éxito se
    dispara un evento para tal fin, en donde podemos realizar
    acciones
    inmediatas en el momento preciso en que se logra establecer la
    conexión con el servidor. El evento es el
    siguiente:

    Private Sub
    Winsock1_Connect()

    'desplegamos un mensaje en la
    ventana

    Text1.Text = Text1.Text & _

    "*** Conexion establecida." &
    vbCrLf

    'desplazamos el
    scroll

    Text1.SelStart = Len(Text1.Text)

    End Sub

    En este caso solo nos limitamos a mostrar un mensaje en
    pantalla especificando que la conexión se ha realizado con
    éxito.

    En este momento ya tenemos creado los lazos
    básicos para realizar cualquier intercambio de datos con
    el servidor, ya sea texto ASCII o datos
    binarios.

    También hay que tener presente que en cualquier
    momento el servidor nos puede cerrar la conexión, o bien
    cerrarse por algún error, para ello es que contamos con el
    evento "Close", que se dispara al perder la conexión con
    el servidor:

    Private Sub
    Winsock1_Close()

    'cierra la conexion

    Winsock1.Close

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Conexion
    cerrada por el servidor." & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    Aquí solo desplegamos un mensaje en la pantalla
    informando del evento ocurrido, y cerrando previamente el Socket
    para asegurarnos de que este actualice sus valores según
    el estado actual.

    En cambio si
    queremos cerrar nosotros mismos la conexión con el
    servidor basta con llamar al método "Close"
    directamente:

    Private Sub
    Command3_Click()

    'cierra la conexion

    Winsock1.Close

    'desplegamos un mensaje en la
    ventana

    Text1.Text = Text1.Text & _

    "*** Conexion cerrada por el usuario." &
    vbCrLf

    'desplazamos el scroll

    Text1.SelStart = Len(Text1.Text)

    End Sub

     

    3. Enviando/recibiendo datos

    Una vez realizada con éxito nuestra
    conexión, solo resta comenzar a transferir datos, cabe
    mencionar que estos datos se envían siempre en forma
    binaria aunque sea solo texto, ya que el texto en si es una
    representación grafica de un numero binario, con esto
    quiero expresar que a través de un socket puedes enviar
    texto normal o datos binario, todos como variables de
    tipo String (cadenas).

    Métodos necesarios

    – SendData: Envía datos al otro extremo de la
    conexión (socket remoto).

    – GetData: Recibe datos enviados por el extremo remoto
    (socket remoto).

    Eventos involucrados

    – DataArrival(): Ocurre cuando el socket remoto nos esta
    enviando datos.

    – Error(): Ocurre en caso de errores.

    Para enviar datos utilizamos el método "SendData"
    de la sig. forma:

    Private Sub
    Command1_Click()

    'enviamos el contenido de
    Text2

    Winsock1.SendData Text2.Text &
    vbCrLf

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Cliente >"
    & Text2.Text & vbCrLf 'mostramos los datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    'borramos Text2

    Text2.Text = ""

    End Sub

    Al método SendData solo se le pasa como
    parámetro el dato a enviar (en este caso el contenido de
    un TextBox + los caracteres de nueva línea y retorno de
    carro) y este lo envía inmediatamente al socket
    remoto.

    Cuando el socket remoto nos envía un dato (de la
    misma forma que realizamos anteriormente) se nos genera el evento
    "DataArrival()" indicando que tenemos nueva información
    disponible, y esta información la cogemos con el
    método "GetData":

    Private Sub
    Winsock1_DataArrival(ByVal bytesTotal As
    Long)

    Dim Buffer
    As String 'variable para guardar los datos

    'obtenemos los datos y los
    guardamos en una variable

    Winsock1.GetData Buffer

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Servidor >"
    & Buffer 'mostramos los
    datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    End Sub

    En este ejemplo solo obtenemos los datos y lo mostramos
    inmediatamente en la ventana del cliente, no hacemos
    ningún tratamiento previo de los datos, como sería
    lo habitual.

    4. Manejo de errores

    Es muy importante tomar alguna acción cuando se
    produzca algún error, aunque esta acción tan solo
    sea cerrar la conexión e informar al usuario de lo
    ocurrido.

    Para el manejo de errores producidos durante la
    conexión contamos con un evento dedicado, llamado
    "Error()" el cual retorna varios valores para darnos
    información al respecto, entre ellos los mas comunes
    son:

    Number As Integer

    Informa sobre el numero del error
    producido

    Description As String

    Entrega una breve descripción del error

    En caso de producirse algún error la
    acción más simple de realizar es simplemente cerrar
    la conexión con el método "Close":

    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)

    'cerramos la conexion

    Winsock1.Close

    'mostramos informacion sobre el
    error

    MsgBox "Error numero " & Number & ": "
    & Description, vbCritical

    End Sub

    5. Prueba de la aplicación

    En este punto ya estamos listo para comenzar a usar
    nuestro programa cliente, solo le damos a ejecutar desde el
    entorno del Visual Basic o bien compilamos y ejecutamos el
    archivo.

    Para asegurarnos que todo ha salido bien, vamos a
    realizar una pequeña prueba, conectaremos a www.google.com
    y solicitaremos la página de inicio:

    En el campo "Servidor" de nuestro programa escribimos
    "www.google.com", y en el campo "Puerto" colocamos el "80". Le
    damos al botón "Conectar".

    Si todo va bien, deberíamos obtener el mensaje
    "Conexión establecida", si es así entonces en el
    campo de enviar texto, escribimos "GET / HTTP/1.1":

    Y para enviar presionamos dos veces el botón
    "Enviar". La razón de esto es para que envié la
    cadena que escribimos mas dos caracteres de retorno de carro o
    nueva línea (vbCrLf), esto por especificaciones del
    protocolo HTTP (que es lo que estamos utilizando
    aquí).

    Deberíamos ver algo como esto:

    Si recibimos texto desde el servidor (Las cadenas que
    inician con "Servidor >") es que nuestro cliente funciona
    perfectamente y hemos realizado la conexión, enviado y
    recibido datos con éxito. Ya podemos descasar un rato y
    celebrar :).

    MI
    PRIMERA APLICACIÓN SERVIDOR

    Vamos a realizar una aplicación que se mantenga a
    la escucha de una conexión entrante y la acepte,
    podrá enviar y recibir datos desde el cliente.

    Al principio será mono-conexión, es decir,
    solo permitirá una conexión a la vez al servidor,
    pero luego la implementaremos para múltiples
    conexiones.

    Algunas partes del código para el servidor son
    idénticas al del cliente (realizado anteriormente)
    así que solo me limitare a mostrar como queda el
    código y la explicación de la misma se
    entenderá que es la correspondiente a la del
    cliente.

    1. Creando la interfaz del usuario

    Realiza un formulario como el mostrado abajo, con los
    nombres por defecto de cada control y guarda el proyecto con el
    nombre "Servidor.vbp".

    2. Implementando la conexión

    Al igual que en el cliente, lo primero es habilitar el
    socket para que pueda quedar esperando una conexión, se
    dice que queda "a la escucha de". Para esto solo necesitamos un
    botón "Escuchar" y como datos un puerto local (a
    elección) en el cual deseamos recibir conexiones
    entrantes.

    Propiedades necesarias

    – LocalPort: Asignamos el puerto local en el cual
    deseamos recibir conexiones.

    Métodos necesarios

    – Listen(): Escucha peticiones entrantes.

    – Close(): Cierra la conexión al
    servidor.

    Eventos involucrados

    – ConnectionRequest(): Ocurre cuando un cliente nos
    solicita una conexión al servidor.

    – Close(): Ocurre cuando el servidor nos cierra la
    conexión.

    – Error(): Ocurre en caso de errores.

    El código utilizado para el botón
    "Escuchar" es el siguiente:

    Private Sub
    Command2_Click()

    'cerramos cualquier conexion
    previa

    Winsock1.Close

    'asignamos el puerto local que
    abriremos

    Winsock1.LocalPort = Text3.Text

    'deja el socket esuchando
    conexiones

    Winsock1.Listen

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Esuchando
    conexiones." & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    La primera línea de código cierra la
    conexión actual, para luego poder modificar los datos y
    crear una nueva conexión sin que nos de
    errores.

    La siguiente línea le dice en que puerto deseamos
    recibir conexiones, y luego llama al socket para que quede a la
    escucha de conexiones en ese puerto.

    Hasta aquí el socket solo esta "escuchando"
    conexiones, es decir aun nadie se puede conectar al servidor
    completamente porque no se ha implementado esa parte por el
    momento.

    Esto solo nos permite avisarnos cada vez que un cliente
    se quiera conectar o bien cada vez que un cliente "Solicita una
    conexión entrante". Cuando este sucede se genera el evento
    "ConnectionRequest()":

    Private Sub
    Winsock1_ConnectionRequest(ByVal requestID
    As Long)

    'mostramos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Peticion
    numero " & requestID & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    'cerramos previamente el
    socket

    Winsock1.Close

    'aceptamos la
    conexion

    Winsock1.Accept requestID

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Conexion
    aceptada, listo para interactuar." &
    vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    Con estas líneas ya estamos conectado
    completamente, pero de seguro que quedan
    muchas dudas, y precisamente este punto es uno de los mas
    importantes, así que pasare a detallar cada
    cosa.

    Lo primero que habíamos realizado es dejar el
    socket a la escucha de conexiones (para esto utilizamos el
    método "Listen"). Con esto ya tenemos un puerto abierto y
    atento a toda actividad.

    Cuando un "Cliente" se intenta conectar a ese puerto, el
    socket lo detectara y para ello generara el evento
    "ConnectionRequest()" que significa "Petición de
    conexión" y además le asigna una identidad a
    esa "Petición" que identifica al "Cliente" remoto. Esta
    identidad es pasada como parámetro en el evento
    "ConnectionRequest()" con el nombre de "requestID" y es de tipo
    "Long".

    Cuando se genera el evento lo que tenemos que hacer es
    "Aceptar" la conexión entrante "requestID" mediante el
    metodo "Accept", si no lo hacemos al llegar al "End Sub" del
    evento, la conexión del "Cliente" será cerrada
    automáticamente.

    Algo interesante es ver que antes de aceptar la
    conexión con "Accept" primero cerramos la conexión
    con "Close", esto que puede parecer ilógico no lo es,
    porque el socket lo teníamos ocupado y activo "escuchando
    conexiones", y ahora necesitamos que establezca una
    conexión par a par con el cliente, por ello es que
    cerramos la función de "Escuchar conexiones del socket" y
    le decimos que acepte la conexión entrante y así
    automáticamente se conecta en forma directa con el cliente
    y ya no entenderá nuevas conexiones entrantes. (No puede
    realizar dos funciones a la
    vez)

    Para cerrar la conexión basta con usar el
    método "Close" en cualquier momento:

    Private Sub
    Command3_Click()

    'cierra la conexion

    Winsock1.Close

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Conexion
    cerrada por el usuario." & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    Private Sub
    Winsock1_Close()

    'cierra la conexion

    Winsock1.Close

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Conexion
    cerrada por el Cliente." & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    3. Enviando/recibiendo datos

    Esto es idéntico al explicado en la parte del
    cliente:

    Private Sub
    Command1_Click()

    'enviamos el contenido de
    Text2

    Winsock1.SendData Text2.Text &
    vbCrLf

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Servidor >"
    & Text2.Text & vbCrLf 'mostramos los datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    'borramos Text2

    Text2.Text = ""

    End Sub

    Private Sub
    Winsock1_DataArrival(ByVal bytesTotal
    As Long)

    Dim Buffer
    As String 'variable para guardar los datos

    'obtenemos los datos y los
    guardamos en una variable

    Winsock1.GetData Buffer

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Cliente >"
    & Buffer 'mostramos los
    datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    End Sub

    4. Manejo de errores

    Esto es idéntico al explicado en la parte del
    cliente:

    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)

    'cerramos la conexion

    Winsock1.Close

    'mostramos informacion sobre el
    error

    MsgBox "Error numero " & Number & ": "
    & Description, vbCritical

    End Sub

    5. Prueba de la aplicación

    Después de mucho "copiar/pegar" :), ya estamos
    listos con nuestra aplicación servidor y listos para
    realizar las primeras pruebas y ver
    si todo trabaja correctamente.

    Lo primero, ejecuta la aplicación servidor y
    donde dice "Puerto" coloca cualquier número de los 65.535
    disponibles, por ej. el "23". Luego dale al botón
    "Escuchar":

    Ahora ejecuta la aplicación Cliente y en
    "Servidor" coloca "localhost" o "127.0.0.1" y en "Puerto" coloca
    el "23". Dale al botón "Conectar".

    En el servidor obtienes:

    Ya estamos listos y trabajando con nuestra
    aplicación Cliente/Servidor!!, ¿No lo crees?,
    prueba a enviar texto entre cliente->servidor y
    servidor->cliente y compruébalo tu mismo:

    Ahora que sabemos que todo trabaja correctamente te
    invito a hacer una prueba más. Con la conexión
    establecida y funcionando de par a par ente cliente/servidor,
    ejecuta una nueva aplicación "Cliente" e intenta conectar
    al servidor en el mismo puerto (en este caso servidor "localhost"
    y puerto "23"), y espera los resultados:

    Nos dice que no logra establecer la conexión,
    este es el mismo mensaje que entrega si el servidor al que
    intenta conectar No tiene ningún puerto abierto!!,
    lo que sucede es que el servidor ya no se encuentra "a la escucha
    de conexiones" y por lo tanto no atenderá nuevas
    peticiones de conexión.

    APLICACIÓN SERVIDOR
    MULTI-CONEXIÓN

    Ahora nos encontramos con los conocimientos suficientes
    para implementar un servidor que pueda aceptar un número
    indefinido de conexiones entrantes.

    En este proyecto usaremos el mismo código fuente
    del servidor mono-conexión utilizado anteriormente, ya que
    los cambios son muy pocos en realidad.

    Bien, entonces abrimos el proyecto del servidor
    mono-conexión y lo guardamos como "Servidor Multi.vbp"
    para comenzar a trabajar.

    La interfaz la dejaremos tal cual, todo el cambio
    será en relación al código mismo y a la
    modificación de algunos controles. También
    trabajaremos con arreglo de controles, si nunca lo has hecho
    podrías buscar un poco de información al respecto o
    bien intentar seguir adelante, que lo explicare de forma
    breve.

    1. Vista general del funcionamiento

    Como vimos anteriormente en el Servidor
    mono-conexión, dejábamos un socket a la escucha de
    conexiones entrantes, y al recibir una petición de
    conexión (evento "ConnectionRequest") le decíamos
    al Winsock que aceptara esa identidad y este a su vez
    establecía una conexión con el cliente.

    Los principios para
    crear un servidor multi-conexión son los mismos, salvo que
    necesitamos dejar un socket escuchando permanentemente conexiones
    entrantes, este nunca se debe cerrar (al contrario de lo que
    pasaba en el caso del servidor mono-conexión), entonces
    ¿como podemos aceptar una conexión si no podemos
    cerrar el socket que tenemos a la escucha?, ¿acaso podemos
    dejar un mismo socket escuchando conexiones y atendiendo otra a
    la vez?, la respuesta es No podemos, pero nada nos impide
    hacer que otro socket que se encuentra inactivo acepte y atienda
    una petición de conexión. De esta forma el trabajo
    total se reparte entre varios sockets: un socket permanentemente
    escuchando peticiones de conexión (recepcionista) y otros
    tantos socket que se encargan de atender a cada uno de los
    clientes (ejecutivos).

    2. Creando el arreglo de WinSocks

    Para poder trabajar con varias conexiones a la vez
    necesitamos varios sockets disponibles, ya que cada uno solo
    puede trabajar con una sola conexión, y como en
    principio no conocemos la cantidad de Winsocks que necesitaremos
    debemos inclinarnos por crear Arreglos de controles Winsock e
    irlos cargando dinámicamente.

    Si lo deseas también puedes crear una N cantidad
    de Winsocks y solo trabajar con ellos, pero tu número
    máximo de conexiones posibles será el máximo
    de Winsocks que tengas.

    Entonces, para crear el arreglo debemos seguir los sig.
    pasos:

    1. Agregar un nuevo Winsock al formulario
      (Winsock2)
    2. Copiar el control (Clic derecho sobre este y
      seleccionar "Copiar")
    3. Pegar el control en el formulario, y cuando pregunte
      por si deseas crear el arreglo dile que "Si". (Clic derecho
      sobre el formulario y seleccionar "Pegar")
    4. Borramos el nuevo Winsock que se ha creado
      (Winsock2(1)).

    La razón de borrar este último Winsock es
    porque no nos hace falta, como mencionamos en un principio,
    nosotros crearemos los Winsocks necesarios de forma dinámica, solo necesitamos tener existente
    el Winsock2 de índice cero.

    3. Limpiando código innecesario

    En realidad no hay código innecesario pero si
    código que debe cambiar de lugar, como veremos en su
    momento, por ahora solo nos limitaremos a borrar todo el
    código del evento "Winsock1_DataArrival" ya que nunca lo
    usaremos en este Winsock porque solo trabajara como repartidor de
    trabajo y
    "Winsock1_ConnectionRequest" que será implementada mas
    adelante, lo mismo para la acción del botón
    "Enviar" (Command1_Click).

    4. Enviando/recibiendo datos

    Vamos a ver como se realizan las acciones de recibir y
    enviar datos cuando tenemos arreglos de sockets (Winsock2()), nos
    guardaremos la
    administración de las peticiones de conexiones para
    más adelante.

    Para enviar datos (mediante el botón "enviar")
    podemos hacerlo directamente con algún socket
    específico, definiendo su identidad, o bien con todos los
    sockets recorriendo el arreglo. Esto último es lo que
    haremos a modo de ejemplo:

    Private Sub
    Command1_Click()

    Dim
    numElementos As
    Integer 'numero de
    sockets

    Dim i
    As Integer 'contador

    'obtiene la cantidad de Winsocks
    que tenemos

    numElementos = Winsock2.UBound

    'recorre el arreglo de
    sockets

    For i = 0
    To
    numElementos

    'si el socket se encuentra
    conectado…

    If
    Winsock2(i).State = sckConnected
    Then

    'enviamos el contenido de
    Text2

    Winsock2(i).SendData Text2.Text &
    vbCrLf

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Sock" & i
    & ":Servidor >" & Text2.Text &
    vbCrLf 'mostramos los
    datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    End If

    Next

    'borramos Text2

    Text2.Text = ""

    End Sub

    Y cuando recibamos datos desde el cliente se nos
    generara el evento "Winsock2_DataArrival" que ahora incluye un
    nuevo parámetro "Index" de tipo "Integer" y contiene el
    número o índice del socket que genera el evento
    (todo en relación al arreglo de sockets).

    Para recibir datos solo tenemos que tomar en cuenta ese
    "Index" y el resto es igual a lo visto en el servidor de
    conexión mono-usuario:

    Private Sub
    Winsock2_DataArrival(Index As Integer, ByVal bytesTotal
    As Long)

    Dim Buffer
    As String 'variable para guardar los datos

    'obtenemos los datos y los
    guardamos en una variable

    Winsock2(Index).GetData Buffer

    'apuntamos al final del
    contenido del TextBox e

    'insertamos los nuevos datos
    obtenidos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    Text1.Text = Text1.Text & "Sock" & Index
    & ":Cliente >" & Buffer 'mostramos los datos

    Text1.SelStart = Len(Text1.Text)
    'coloca el cursor al final del
    contenido

    End Sub

    5. Evento Error y Close

    El código para los eventos "Error" y "Close" del
    arreglo de sockets es muy simple:

    Private Sub
    Winsock2_Close(Index As Integer)

    'cierra la conexion

    Winsock2(Index).Close

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "Sock" & Index
    & ":*** Conexion cerrada por el Cliente." &
    vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    Private Sub
    Winsock2_Error(Index As Integer, 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)

    'cerramos la conexion

    Winsock2(Index).Close

    'mostramos informacion sobre el
    error

    MsgBox "Error numero " & Number & ": "
    & Description, vbCritical

    End Sub

    5. Escuchando y atendiendo a las
    conexiones

    El siguiente paso será recibir las peticiones de
    conexión y asignárselas a cada socket para que las
    atienda. Para ello necesitaremos crear un nuevo socket cada vez
    que recibamos una petición de conexión y decirle
    que acepte la identidad de la conexión.

    Para facilitar las cosas nosotros haremos una
    función que se encargue de crear los sockets y que
    además devuelva el número del nuevo socket
    creado:

    'Carga un nuevo socket al
    arreglo y devuelve su indice

    Private Function
    NuevoSocket() As
    Integer

    Dim
    numElementos As
    Integer 'numero de
    sockets

    Dim i
    As Integer 'contador

    'obtiene la cantidad de Winsocks
    que tenemos

    numElementos = Winsock2.UBound

    'recorre el arreglo de
    sockets

    For i = 0
    To
    numElementos

    'si algun socket ya creado esta
    inactivo

    'utiliza este mismo para la
    nueva conexion

    If
    Winsock2(i).State = sckClosed Then

    NuevoSocket = i 'retorna el indice

    Exit Function
    'abandona la funcion

    End If

    Next

    'si no encuentra sockets
    inactivos

    'crea uno nuevo y devuelve su
    identidad

    Load Winsock2(numElementos + 1)
    'carga un nuevo socket al
    arreglo

    'devuelve el nuevo
    indice

    NuevoSocket = Winsock2.UBound

    End Function

    Esta función no solo crea un nuevo socket, sino
    que además si encuentra alguno que se había creado
    antes y este se encuentra inactivo (desconectado) lo selecciona
    para volverlo a utilizar y así aprovechar mas los recursos del
    sistema.

    Nota: Esta no es la forma más óptima de
    manejar arreglos de objetos, ya que no nos permite ir liberando
    de la memoria
    (borrando) los sockets que ya no son utilizados y solo se limita
    a crear nuevos.

    Ahora nos situamos en el evento "ConnectionRequest()"
    del "Winsock1" (el que hará de recepción) y
    escribimos el siguiente código:

    Private Sub
    Winsock1_ConnectionRequest(ByVal requestID
    As Long)

    Dim
    numSocket As
    Integer 'el numero del socket

    'mostramos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "*** Peticion
    numero " & requestID & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    'creamos un nuevo
    socket

    numSocket = NuevoSocket

    'aceptamos la conexion con el
    nuevo socket

    Winsock2(numSocket).Accept requestID

    'desplegamos un mensaje en la
    ventana

    Text1.SelStart = Len(Text1.Text)

    Text1.Text = Text1.Text & "Sock" &
    numSocket & ":*** Conexion aceptada, listo para
    interactuar." & vbCrLf

    Text1.SelStart = Len(Text1.Text)

    End Sub

    Aquí lo primero es crear un nuevo socket (o
    reutilizar alguno disponible) y decirle a ese socket que acepte
    aquella conexión. Una vez realizado esto ya estamos libres
    nuevamente para recibir otra conexión.

    También es posible denegar conexiones realizadas
    desde alguna IP especifica, para ello solo hay que revisar la
    propiedad "Winsock1.RemoteHostIP" y ver si aceptamos su
    conexión o bien se la rechazamos con "Close".

    6. Prueba de la aplicación

    Ahora que todo parece estar completo, realizaremos la
    prueba del servidor.

    Ejecuta la aplicación, como "Puerto" coloca el
    "23" y dale al botón "Escuchar".

    Ahora ejecuta dos aplicaciones "Cliente" y
    conéctalos al puerto "23" de "Localhost". Notaras que ya
    no da el error que vimos con el servidor mono-conexión y
    que ambos se encuentran conectados:

    Prueba a enviar mensajes entre ellos y veras que todo
    trabaja perfectamente!!, puedes identificar cada conexión
    porque en el mensaje aparece "SockN" donde "N" es el
    índice del socket, así sabrás en cada
    momento que socket es el que esta enviando el mensaje:

    y ya funciona todo ok!.

    CONCLUSIÓN

    Hemos llegado al final de este tutorial, y hemos
    aprendido a realizar conexión Cliente/Servidor mono y
    multi-conexiones de forma básica, digo básica
    porque hay mejores maneras de implementarlas y mas minuciosas,
    pero esta es la base de todas ellas, y el resto lo
    obtendrás por la practica.

    Espero que este texto les halla sido de utilidad y
    cualquier duda o errores encontrados no dudes en
    comunicármelo, que lo corregiré tan pronto como
    pueda.

    Por ultimo los códigos fuente de los proyectos
    aquí realizados los puedes bajar desde la pagina
    Web http://www.gemu.da.ru.

     

    Gemu –

    www.gemu.da.ru

    Todos los derechos reservados –
    Septiembre de 2005

    Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

    Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

    Categorias
    Newsletter