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.
- Conexión por socket en Visual Basic 6.0 y anteriores.
- Conexión por socket en Visual Basic .Net de Visual Studio 2010.
- AjpdSoft Socket VB.Net en funcionamiento.
- Artículos relacionados.
- Créditos.
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":
En la pestaña "Controles" buscamos "Microsoft Winsock Control 6.0":
C:/Windows/system32/MSWINSCK.OCK
lo marcamos y pulsamos "Aceptar":
Nos agregará un nuevo elemento a la paleta de componentes:
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:
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<em> 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 </em> |
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:
123456789101112 <em>Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)'Mostrar mensaje cuando un cliente se conectetxtLog.Text = txtLog.Text & _"Petición de conexión cliente " & requestID & vbCrLf'Cerrar el socketWinsock1.Close'Aceptar la conexiónWinsock1.Accept requestID'desplegamos un mensaje en la ventanatxtLog.Text = txtLog.Text & "Cliente conectado: " & _requestID & vbCrLfEnd Sub</em>
Para desactivar el modo escucha y cerrar todas las conexiones actuales en el servidor agregaremos el botón "btDesactivarEscucha" con el siguiente código:
1234 <em>Private Sub btDesactivarEscucha_Click()'Cerrar conexión SocketWinsock1.CloseEnd Sub</em>
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:
12345678 <em>Private Sub Winsock1_Close()txtLog.Text = txtLog.Text & _"Desactivado modo escucha, no se aceptarán conexiones" & vbCrLfbtDesactivarEscucha.Enabled = FalsebtEscuchar.Enabled = TruetxtMensaje.Enabled = FalsebtEnviarMensaje.Enabled = FalseEnd Sub</em>
Para agregar un botón al formulario del servidor que envíe un mensaje al cliente conectado (btEnviarMensaje) usaremos el siguiente código:
123 <em>Private Sub btEnviarMensaje_Click()Winsock1.SendData txtMensaje.Text & vbCrLfEnd Sub</em>
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:
12345678 <em>Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)Dim datosRecibidos As String'Obtener los datos enviados por el clienteWinsock1.GetData datosRecibidostxtMensajesClientes.Text = txtMensajesClientes.Text & _"Mensaje: " & datosRecibidosEnd Sub</em>
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:
1234567891011 <em>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ónWinsock1.Close'Mostramos el errorMsgBox "Error con WinSock: " & Number & ": " & _Description, vbCriticalEnd Sub</em>
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:
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":
12345678910 <em>Private Sub btConectar_Click()'Asignamos la IP o hostname a WinsockWinsock1.RemoteHost = txtServidor.Text'Asignamos el puerto a WinsockWinsock1.RemotePort = txtPuerto.Text'Desconectamos por si acaso estaba conectado yaWinsock1.Close'Realizamos la conexión mediante Socket al servidor y puertoWinsock1.ConnectEnd Sub</em>
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:
123456 <em>Private Sub Winsock1_Connect()'desplegamos un mensaje en la ventanatxtLog.Text = txtLog.Text & _"Conexión establecida con servidor " & _txtServidor.Text & ":" & txtPuerto.Text & vbCrLfEnd Sub</em>
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:
1234 <em>Private Sub Winsock1_Close()txtLog.Text = txtLog.Text & _"Desconectado de servidor" & vbCrLfEnd Sub</em>
En el botón "btDesconectar" colocaremos el siguiente código, con este botón el usuario podrá desconectarse del servidor cuando lo estime pertinente:
1234 <em>Private Sub btDesconectar_Click()'Cerramos la conexión con el servidorWinsock1.CloseEnd Sub</em>
El botón para enviar un mensaje de texto al servidor "btEnviarMensaje" tendrá el siguiente código:
1234 <em>Private Sub btEnviar_Click()'Enviar txtMensaje a servidorWinsock1.SendData txtMensaje.Text & vbCrLfEnd Sub</em>
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:
1234567 <em>Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)Dim datosRecibidos As String'Se obtienen los datos enviados por el servidorWinsock1.GetData datosRecibidostxtMensajesServidor = txtMensajesServidor.Text & _"Servidor: " & datosRecibidosEnd Sub</em>
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:
123456789101112 <em>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ónWinsock1.Close'Mostramos el errorMsgBox "Error con WinSock: " & Number & ": " & _Description, vbCriticalEnd Sub</em>
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:
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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 <em>Imports System.ThreadingImports System.Net.SocketsImports System.TextPublic Class ClaseServidorSocket'Esta estructura permite guardar la información sobre un clientePrivate Structure datosClienteConectadoPublic socketConexion As Socket 'Socket para mantener la conexión con clientePublic Thread As Thread 'Hilo para mantener escucha con el clientePublic UltimosDatosRecibidos As String 'Últimos datos enviados por el clienteEnd StructurePrivate tcpLsn As TcpListener 'Para realizar la escuchas de conexiones de clientesPrivate Clientes As New Hashtable() 'Datos de los clientes conectadosPrivate tcpThd As ThreadPrivate IDClienteActual As Net.IPEndPoint 'Último cliente conectadoPrivate m_PuertoDeEscucha As StringPublic 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 escuchaProperty Puerto() As IntegerGetPuerto = m_PuertoDeEscuchaEnd GetSet(ByVal Value As Integer)m_PuertoDeEscucha = ValueEnd SetEnd Property'Procedimiento para establecer el servidor en modo escuchaPublic Sub IniciarEscucha()tcpLsn = New TcpListener(Puerto)'Iniciar escuchatcpLsn.Start()'Crear hilo para dejar escuchando la conexión de clientestcpThd = New Thread(AddressOf EsperarConexionCliente)tcpThd.Start()End Sub'Procedimiento para detener la escucha del servidorPublic Sub DetenerEscucha()CerrarTodosClientes()tcpThd.Abort()tcpLsn.Stop()End SubPublic Function ObtenerDatos(ByVal IDCliente As Net.IPEndPoint) As StringDim InfoClienteSolicitado As datosClienteConectado'Obtengo la informacion del cliente solicitadoInfoClienteSolicitado = Clientes(IDCliente)ObtenerDatos = InfoClienteSolicitado.UltimosDatosRecibidosEnd Function'Cierra la conexión de un cliente conectadoPublic Sub cerrarConexionCliente(ByVal IDCliente As Net.IPEndPoint)Dim InfoClienteActual As datosClienteConectado'Obtener información del cliente indicadoInfoClienteActual = Clientes(IDCliente)'Cerrar conexión con clienteInfoClienteActual.socketConexion.Close()End Sub'Cerrar todas la conexión de todos los clientes conectadosPublic Sub CerrarTodosClientes()Dim InfoClienteActual As datosClienteConectado'Cerrar conexión de todos los clientesFor Each InfoClienteActual In Clientes.ValuesCall cerrarConexionCliente(InfoClienteActual.socketConexion.RemoteEndPoint)NextEnd Sub'Enviar mensaje a cliente indicadoPublic 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 mensajeCliente = Clientes(IDCliente)'Enviar mensaje a clienteCliente.socketConexion.Send(Encoding.ASCII.GetBytes(Datos))End Sub'Enviar mensaje a todos los clientes conectados al servidorPublic Sub enviarMensajeTodosClientes(ByVal Datos As String)Dim Cliente As datosClienteConectadoFor Each Cliente In Clientes.ValuesenviarMensajeCliente(Cliente.socketConexion.RemoteEndPoint, Datos)NextEnd 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 datosClienteConectadoWhile True'Se guarda la información del cliente cuando se recibe la conexión'Quedará esperando la conexión de un nuevo clientedatosClienteActual.socketConexion = tcpLsn.AcceptSocket()'Con el IDClienteActual se identificará al cliente conectadoIDClienteActual = datosClienteActual.socketConexion.RemoteEndPoint'Crear un hilo para que quede escuchando los mensajes del clientedatosClienteActual.Thread = New Thread(AddressOf LeerSocket)'Agregar la información del cliente conectado al arraySyncLock MeClientes.Add(IDClienteActual, datosClienteActual)End SyncLock'Generar evento NuevaConexionRaiseEvent NuevaConexion(IDClienteActual)'Iniciar el hilo que escuchará los mensajes del clientedatosClienteActual.Thread.Start()End WhileEnd Sub'Procedimiento para leer datos enviados por el clientePrivate Sub LeerSocket()Dim IDReal As Net.IPEndPoint 'ID del cliente que se va a escucharDim Recibir() As Byte 'Array donde se guardarán los datos que lleguenDim InfoClienteActual As datosClienteConectado 'Datos del cliente conectadoDim Ret As Integer = 0IDReal = IDClienteActualInfoClienteActual = Clientes(IDReal)While TrueIf InfoClienteActual.socketConexion.Connected ThenRecibir = New Byte(100) {}Try'Esperar a que lleguen un mensaje desde el clienteRet = InfoClienteActual.socketConexion.Receive(Recibir,Recibir.Length, SocketFlags.None)If Ret > 0 Then'Guardar mensaje recibidoInfoClienteActual.UltimosDatosRecibidos =Encoding.ASCII.GetString(Recibir)Clientes(IDReal) = InfoClienteActual'Generar el evento DatosRecibidos'para los datos recibidosRaiseEvent DatosRecibidos(IDReal)Else'Generar el evento ConexionTerminada'de finalización de la conexiónRaiseEvent ConexionTerminada(IDReal)Exit WhileEnd IfCatch e As ExceptionIf Not InfoClienteActual.socketConexion.Connected Then'Generar el evento ConexionTerminada'de finalización de la conexiónRaiseEvent ConexionTerminada(IDReal)Exit WhileEnd IfEnd TryEnd IfEnd WhileCall 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 clienteInfoClienteActual = Clientes(IDCliente)TryInfoClienteActual.Thread.Abort()Catch e As ExceptionSyncLock Me'Eliminar el cliente del arrayClientes.Remove(IDCliente)End SyncLockEnd TryEnd SubEnd Class</em>
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":
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 <em>Public Class formSocketServidorDim WithEvents socketServidor As New ClaseServidorSocket()'Iniciar el servidor, establecer el modo escucha'para recibir conexión de clientesPrivate Sub btEscuchar_Click(sender As System.Object,e As System.EventArgs) Handles btEscuchar.ClickIf txtPuerto.Text <> "" ThenTrysocketServidor.Puerto = txtPuerto.TextsocketServidor.IniciarEscucha()btEscuchar.Enabled = FalsetxtPuerto.Enabled = FalsetxtMensaje.Enabled = TruebtEnviarMensaje.Enabled = TruebtDetenerEscucha.Enabled = TruetxtMensaje.Focus()Catch err As ExceptionMsgBox("Se ha producido un error al intentar " & _"establecer escucha por el puerto " & _txtPuerto.Text & vbCrLf & vbCrLf & err.Message,MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)End TryElseMsgBox("Debe indicar el puerto por el que establecer la escucha.",MsgBoxStyle.Information + MsgBoxStyle.OkOnly)txtPuerto.Focus()End IfEnd Sub'Evento que se ejecutará cuando un nuevo cliente se conectePrivate Sub socketServidor_NuevaConexion(ByVal IDTerminal As _System.Net.IPEndPoint) Handles socketServidor.NuevaConexiontxtLog.Text = txtLog.Text & vbCrLf & "Conectado cliente: " &IDTerminal.Address.ToString & ", Puerto: " & IDTerminal.PortEnd Sub'Evento que se ejecutará cuando finalice la conexión de un clientePrivate Sub socketServidor_ConexionTerminada(ByVal IDTerminal As _System.Net.IPEndPoint) Handles socketServidor.ConexionTerminadatxtLog.Text = txtLog.Text & vbCrLf & "Desconectado cliente: " &IDTerminal.Address.ToString & ", Puerto: " & IDTerminal.PortbtEscuchar.Enabled = TruetxtPuerto.Enabled = TrueEnd Sub'Evento que se ejecutará cuando se reciban datos de los clientes conectadosPrivate Sub socketServidor_DatosRecibidos(ByVal IDTerminal As _System.Net.IPEndPoint) Handles socketServidor.DatosRecibidos'Datos del cliente que se conectatxtLog.Text = txtLog.Text & vbCrLf &"Cliente: " & IDTerminal.Address.ToString &", Puerto: " & IDTerminal.Port'Mensaje recibido del clientetxtMensajeRecibido.Text = IDTerminal.Address.ToString & " " & Now & " " &txtMensajeRecibido.Text & " " & socketServidor.ObtenerDatos(IDTerminal)End Sub'Enviar mensaje a todos los clientes conectadosPrivate Sub btEnviarMensaje_Click(sender As System.Object,e As System.EventArgs) Handles btEnviarMensaje.ClicksocketServidor.enviarMensajeTodosClientes(txtMensaje.Text)End Sub'Detener modo escucha, no se recibirán conexiones de clientesPrivate Sub btDetenerEscucha_Click(sender As System.Object,e As System.EventArgs) Handles btDetenerEscucha.ClickbtEscuchar.Enabled = TruetxtPuerto.Enabled = TruetxtMensaje.Enabled = FalsebtEnviarMensaje.Enabled = FalsebtDetenerEscucha.Enabled = FalseTrysocketServidor.DetenerEscucha()Catch err As ExceptionMsgBox("Error al detener la escucha:" + vbCrLf +vbCrLf + err.Message,MsgBoxStyle.Information + MsgBoxStyle.OkOnly)End TryEnd Sub'Finalizamos con End para cerrar el hilo (thread) abiertoPrivate Sub formSocketServidor_FormClosed(sender As System.Object,e As System.Windows.Forms.FormClosedEventArgs) _Handles MyBase.FormClosedEndEnd SubEnd Class</em>
Aplicación cliente para conexión por socket con Visual Basic .Net
En la aplicación cliente agregaremos los siguientes componentes:
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:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 <em>Imports System.Net.SocketsImports System.ThreadingImports System.TextImports System.IOPublic Class ClaseClienteSocketPrivate mensajesEnviarRecibir As Stream 'Para enviar y recibir datos del servidorPrivate ipServidor As String 'Dirección IPPrivate puertoServidor As String 'Puerto de escuchaPrivate clienteTCP As TcpClientPrivate hiloMensajeServidor As Thread 'Escuchar mensajes enviados desde el servidorPublic Event ConexionTerminada()Public Event DatosRecibidos(ByVal datos As String)'Dirección IP del servidor al que nos conectaremosPublic Property IP() As StringGetIP = ipServidorEnd GetSet(ByVal Value As String)ipServidor = ValueEnd SetEnd Property'Puerto por el que realizar la conexión al servidorPublic Property Puerto() As IntegerGetPuerto = puertoServidorEnd GetSet(ByVal Value As Integer)puertoServidor = ValueEnd SetEnd Property'Procedimiento para realizar la conexión con el servidorPublic Sub Conectar()clienteTCP = New TcpClient()'Conectar con el servidorclienteTCP.Connect(IP, Puerto)mensajesEnviarRecibir = clienteTCP.GetStream()'Crear hilo para establecer escucha de posibles mensajes'enviados por el servidor al clientehiloMensajeServidor = New Thread(AddressOf LeerSocket)hiloMensajeServidor.Start()End Sub'Procedimiento para cerrar la conexión con el servidorPublic Sub Desconectar()'desconectamos del servidorclienteTCP.Close()'abortamos el hilo (thread)hiloMensajeServidor.Abort()End Sub'Enviar mensaje al servidorPublic Sub EnviarDatos(ByVal Datos As String)Dim BufferDeEscritura() As ByteBufferDeEscritura = Encoding.ASCII.GetBytes(Datos)If Not (mensajesEnviarRecibir Is Nothing) ThenmensajesEnviarRecibir.Write(BufferDeEscritura,0, BufferDeEscritura.Length)End IfEnd SubPrivate Sub LeerSocket()Dim BufferDeLectura() As ByteWhile TrueTryBufferDeLectura = New Byte(100) {}'Esperar a que llegue algún mensajemensajesEnviarRecibir.Read(BufferDeLectura,0, BufferDeLectura.Length)'Generar evento DatosRecibidos cuando se recibien datos desde el servidorRaiseEvent DatosRecibidos(Encoding.ASCII.GetString(BufferDeLectura))Catch e As ExceptionExit WhileEnd TryEnd While'Finalizar conexión y generar evento ConexionTerminadaRaiseEvent ConexionTerminada()End SubEnd Class</em>
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":
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 <em>Public Class formSocketClienteDim WithEvents socketCliente As New ClaseClienteSocketPrivate Sub btEnviar_Click(sender As System.Object,e As System.EventArgs) Handles btEnviar.ClickTry'Enviar mensaje al servidorsocketCliente.EnviarDatos(txtMensaje.Text)Catch err As ExceptionMsgBox("Error al enviar mensaje al servidor." &vbCrLf & vbCrLf & err.Message)End TryEnd Sub'Evento que se ejecuta cuando se reciben datosPrivate Sub socketCliente_DatosRecibidos( _ByVal datos As String) Handles socketCliente.DatosRecibidosbePanel2.Text = "Recibidos datos del servidor"txtMensajeRecibido.Text = Now + " Servidor: " & datosEnd SubPrivate Sub socketCliente_ConexionTerminada() Handles _socketCliente.ConexionTerminadabePanel2.Text = "Conexión finalizada"txtServidor.Enabled = TruetxtPuerto.Enabled = TruebtConectar.Enabled = TruebtDesconectar.Enabled = FalsebtEnviar.Enabled = FalsetxtListaMensajes.Enabled = FalsebePanel1.Text = "No conectado"txtServidor.Focus()End SubPrivate 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 = "" ThenMsgBox("Debe indicar el servidor (IP o hostname) y " _& "el puerto al que realizar la conexión.",MsgBoxStyle.Information + MsgBoxStyle.OkOnly)txtServidor.Focus()ElseTrysocketCliente.IP = txtServidor.TextsocketCliente.Puerto = CInt(txtPuerto.Text)socketCliente.Conectar()txtServidor.Enabled = FalsetxtPuerto.Enabled = FalsebtConectar.Enabled = FalsebtEnviar.Enabled = TruetxtMensaje.Enabled = TruebtDesconectar.Enabled = TruebePanel1.Text = "Conectado"bePanel1.Text = "Conexión establecida a " & _txtServidor.Text & ":" & txtPuerto.TextCatch err As ExceptionbePanel1.Text = "No conectado"MsgBox("Error al conectar al servidor " & txtServidor.Text &vbCrLf & vbCrLf & err.Message,MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)End TryEnd IfEnd SubPrivate Sub formSocketCliente_FormClosed(sender As System.Object,e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosedEndEnd SubPrivate Sub btDesconectar_Click(sender As System.Object, _e As System.EventArgs) Handles btDesconectar.ClicktxtServidor.Enabled = TruetxtPuerto.Enabled = TruebtConectar.Enabled = TruebtEnviar.Enabled = FalsetxtMensaje.Enabled = FalsebtDesconectar.Enabled = FalseTrysocketCliente.Desconectar()Catch err As ExceptionMsgBox("Error al desconectar del servidor " & txtServidor.Text &vbCrLf & vbCrLf & err.Message,MsgBoxStyle.Critical + MsgBoxStyle.OkOnly)End TryEnd SubEnd Class</em>
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":
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":
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":
Si todo es correcto y el Servidor recibe la conexión, la aplicación Servidor mostrará "Conectado cliente …":
Para enviar un mensaje al Servidor lo escribiremos en "Mensaje" y pulsaremos "Enviar":
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":
Los clientes conectados recibirán el mensaje enviado desde el Servidor:
Artículos relacionados
- AjpdSoft Socket VB.Net.
- AjpdSoft Envío SMS.
- Definición Socket Enciclopedia AjpdSoft.
- Cómo enviar mensajes entre aplicaciones Delphi mediante el API de Windows.
- Enviar y recibir datos mediante el protocolo UDP con Borland Delphi 6.
- AjpdSoft Inventario PCs – Código fuente Delphi.
- Cómo conectar dos equipos en red por el puerto paralelo con Windows 98 y XP.
- Insertar evento de Google Calendar con Visual Basic .Net y Google Data API.
- Descarga gratuita código fuente VB.Net AjpdSoft Insertar Evento Google Calendar.
- Crear proceso en segundo plano con barra de progreso en Visual Basic .Net VB.Net.
- Instalar Visual Studio 2010 y desarrollar aplicación con acceso a PostgreSQL.
- El control de errores en Visual Basic .Net.
- Acceso a MySQL mediante Visual Basic .Net y ODBC.
- Acceso a Oracle mediante Microsoft Visual Basic, RDO y ODBC.
- Insertar y extraer documentos en una tabla Oracle con Visual Basic 6.
- Cambiar marcadores de Word por valores del formulario de una aplicación.
- Exportar ListView a fichero CSV VB.Net.
- Función para reemplazar una cadena de texto dentro de otra – Visual Basic.
- Funciones para leer y escribir en ficheros INI VB.Net.
- Enviar y recibir faxes desde un equipo con Windows XP y un módem.
- AjpdSoft Envío EMail SSL.
- AjpdSoft Conexión BD Visual Basic .Net.
- AjpdSoft Puerto Paralelo (código fuente en Delphi).
- Artículos, manuales y trucos del Proyecto AjpdSoft sobre Microsoft Visual Studio.
- Todos los programas con código fuente en Visual Basic.
- Foro del Proyecto AjpdSoft sobre Visual Basic, Visual Studio .Net, VB.Net.
- Realizar una conexión a Internet con la placa Arduino y un módulo GPRS GSM.
Créditos
Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.