Universidad de Buenos Aires Facultad de Ingeniería 66.66- Seminario de Redes Windows Sockets Alumnos: Carlos Martín Calbo Diego Dascanio César Schiraldi 2do Cuatrimestre 2008 79935 80407 79894 Trabajo Práctico N° 3 66.66 Seminario de Redes Indice Introducción........................................................................................................................... 3 ¿Qué es un Socket? ................................................................................................................ 3 Recursos necesarios de un socket. ........................................................................................ 3 Propiedades de un Socket. ..................................................................................................... 3 Kernel. .................................................................................................................................... 4 System Calls (llamadas al sistema). ...................................................................................... 4 Windows Sockets (Winsock) .................................................................................................. 5 Aplicaciones Cliente-Servidor con VisualBasic 6.0 ............................................................. 5 Métodos.................................................................................................................................. 5 Eventos................................................................................................................................... 6 Aplicación mediante VisualBasic 6.0.................................................................................... 7 Diagramas de Flujo. ............................................................................................................ 21 Código fuente del cliente: .................................................................................................... 23 Código fuente del servidor: ................................................................................................. 29 Conclusiones. ....................................................................................................................... 39 2do Cuatrimestre 2008 2 Trabajo Práctico N° 3 66.66 Seminario de Redes Introducción. Mediante el siguiente trabajo pretendemos crear una aplicación cliente-servidor por medio de Winsocks con VisualBasic. La misma permitirá transmitir archivos y descargarlos, además de soportar varias conexiones simultáneas hacia el servidor, el protocolo de conexión será TCP/IP lo que nos permitirá aprovechar las propiedades del mismo. A continuación empezamos dando una descripción teórica de lo que es un socket, winsock, mostramos los diagramas de flujo, el código fuente y por ultimo las conclusiones a las que pudimos arribar mediante la realización del trabajo. ¿Qué es un Socket? Socket designa un concepto abstracto por el cual dos programas (posiblemente situados en computadoras distintas) pueden intercambiarse cualquier flujo de datos, generalmente de manera fiable y ordenada. 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. Recursos necesarios de un socket. Un protocolo de comunicaciones, que permite el intercambio de octetos. Una dirección del Protocolo de Red (Dirección IP, si se utiliza el Protocolo TCP/IP), que identifica una computadora. Un número de puerto, que identifica a un programa dentro de una computadora. Los sockets permiten implementar una arquitectura cliente-servidor. La comunicación ha de 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 fichero 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. 2do Cuatrimestre 2008 3 Trabajo Práctico N° 3 66.66 Seminario de Redes Propiedades de un Socket. Las propiedades de un socket dependen de las características del protocolo en el que se implementan. El protocolo más utilizado es TCP, aunque también es posible utilizar UDP o IPX. Gracias al protocolo TCP, los sockets tienen las siguientes propiedades: Orientado a conexión. Se garantiza la transmisión de todos los octetos sin errores ni omisiones. Se garantiza que todo octeto llegará a su destino en el mismo orden en que se ha transmitido. Estas propiedades son muy importantes para garantizar la corrección de los programas que tratan la información. El protocolo UDP es un protocolo no orientado a la conexión. Sólo se garantiza que si un mensaje llega, llegue bien. En ningún caso se garantiza que llegue o que lleguen todos los mensajes en el mismo orden que se mandaron. Esto lo hace adecuado para el envío de mensajes frecuentes pero no demasiado importantes, como por ejemplo, mensajes para los refrescos (actualizaciones) de un gráfico. Kernel. Es el software responsable de facilitar a los distintos programas acceso seguro al hardware de la computadora o en forma más básica, es el encargado de gestionar recursos, a través de servicios de llamada al sistema. Como hay muchos programas y el acceso al hardware es limitado, el núcleo también se encarga de decidir qué programa podrá hacer uso de un dispositivo de hardware y durante cuánto tiempo, lo que se conoce como multiplexado. Acceder al hardware directamente puede ser realmente complejo, por lo que los núcleos suelen implementar una serie de abstracciones del hardware. Esto permite esconder la complejidad, y proporciona una interfaz limpia y uniforme al hardware subyacente, lo que facilita su uso para el programador. System Calls (llamadas al sistema). Es el mecanismo usado por un programa aplicativo para solicitar un servicio al Sistema Operativo. 2do Cuatrimestre 2008 4 Trabajo Práctico N° 3 66.66 Seminario de Redes Los programas son un conjunto de instrucciones organizadas con un objetivo. Un proceso es conceptualmente un programa en ejecución. En los sistemas operativos multitarea, puede haber varios procesos ejecutándose concurrentemente. Cada proceso puede requerir el uso de recursos de hardware, como periféricos, o espacio de memoria principal, u otros recursos. Dado que el hardware es compartido por múltiples procesos, el acceso a los recursos debe ser administrado para garantizar su correcto uso y evitar problemas de seguridad (si procesos malintencionados desean acceder a recursos asignados a otros procesos). Por estas razones, en los sistemas duales, el acceso al ambiente físico es manejado exclusivamente por el Sistema Operativo. La única forma de acceder al hardware es a través de las llamadas al sistema, que están perfectamente definidas. Mediante un conjunto de llamadas al sistema, el S.O. ofrece un grupo de servicios que facilitan al programador la tarea de establecer una comunicación a través de la red, utilizando en forma transparente los protocolos de capas inferiores (IP, TCP, UDP, etc). Las System calls que se utilizan para establecer la comunicación serán diferentes para el cliente y para el servidor, pero ambos casos requerirán la creación de uno o más sockets. Un socket representa uno de los dos extremos de un canal de comunicación entre procesos. Cada uno de los procesos establece su propio socket para entablar la comunicación. Windows Sockets (Winsock) Provee la interfase requerida por aplicaciones de terceros para trabajar en Microsoft con el protocolo TCP/IP. Winsock es una API Standard que fue desarrollada para proveer una interfase abierta para programación en redes bajo Microsoft Windows. Una implementación de Winsock define una interfase Standard entre una aplicación de Windows y una implementación que utilice el protocolo TCP/IP. Una aplicación escrita sobre esta interfase correrá de la misma forma sobre implementaciones TCP/IP de distintos proveedores. Aplicaciones Cliente-Servidor con VisualBasic 6.0 Para implementar y desarrollar aplicaciones cliente-servidor con VisualBasic 6.0 se utiliza el componente Winsock Control 6.0, a continuación mostramos algunos de los principales métodos y eventos usados por el mismo: Métodos. Sub Accept (requestID As Long) Acepta una petición de conexión entrante. Sub Bind ([LocalPort], [LocalIP]) 2do Cuatrimestre 2008 5 Trabajo Práctico N° 3 66.66 Seminario de Redes 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 Listen () Se pone a la escucha de peticiones de conexión entrantes. Eventos. Event Close () Ocurre cuando la conexión ha 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 envío se haya completado. Event SendProgress (bytesSent As Long, bytesRemaining As Long) Ocurre mientras se esta enviando un dato. 2do Cuatrimestre 2008 6 Trabajo Práctico N° 3 66.66 Seminario de Redes Aplicación mediante VisualBasic 6.0 Nos conectamos entre dos PC’s con la siguiente dirección IP IP Servidor: 192.168.1.100 IP Cliente: 192.168.1.101 Ambos al puerto Tcp: 1200 Captura de la conexión con el servidor remoto: 2do Cuatrimestre 2008 7 Trabajo Práctico N° 3 66.66 Seminario de Redes Observamos que se inicia el tree way hand shake, y se establece la conexión. Probamos solicitar al servidor qué archivos tiene disponibles para compartir. Para ello presionamos el botón solicitar archivos compartidos: 2do Cuatrimestre 2008 8 Trabajo Práctico N° 3 66.66 Seminario de Redes Nos devuelve el listado anterior y sus segmentos asociados son: Aquí se observa el envió de un PSH junto con ACK desde el cliente hacia el servidor, El PSH se debe al envió de un comando que pide los nombres de los archivos que posee el servidor para compartir. Luego el servidor nos contesta con los nombre de los archivos (PSH,ACK) y luego el cliente contesta ACK. 2do Cuatrimestre 2008 9 Trabajo Práctico N° 3 66.66 Seminario de Redes Aquí mostramos en detalle el comando dentro del segmento TCP y los nombres de los archivos devueltos: Ahora solicitamos un archivo deseado, en este caso: Diego3.txt Y los segmentos asociados son: 2do Cuatrimestre 2008 10 Trabajo Práctico N° 3 66.66 Seminario de Redes Observando con mas detalle, vemos que en el primer segmento (el num 7 de la captura), el cliente envía el comando solicitando el archivo Diego3.txt En el siguiente segmento (el 8 de la captura) el servidor nos contesta ACK. Luego nos envía un segmento con los primeros 1460 Bytes del archivo txt que podemos leer en la misma captura: En los siguientes segmentos recibimos mas bytes de datos desde el servidor y también el cliente envía los correspondientes ACK Podemos observar como del lado servidor se fragmenta el segmento en los dos últimos segmentos, uno de 892 bytes y el otro de 31 bytes En total recibimos 4 segmentos de 1460By 1 de 89By y por ultimo uno de 31By En total son: 8223Bytes. Si observamos el recuadro rojo anterior vemos el comando “|Archivo|” , el tamaño del Archivo (8198By) y el nombre del archivo (Diego3.txt). 2do Cuatrimestre 2008 11 Trabajo Práctico N° 3 66.66 Seminario de Redes Por lo tanto debemos restar los bytes que ocupan estos campos y restarlo al total de Bytes recibidos y el resultado debe ser 8198 Bytes: Long(|Archivo|) = 9, Long(8198|) = 5 y Long(Diego3.txt|) = 11 Total = 25 By Entonces: 8223 – 25 = 8198 Esto verifica que recibimos todo el archivo. La transferencia tardó aproximadamente 173 mseg. Para descargar 8.198 By Aprox. = 47 KBy/s ò 380Kb/s despreciando todo el over head. Probemos ahora con un archivo de mayor tamaño: 2do Cuatrimestre 2008 12 Trabajo Práctico N° 3 66.66 Seminario de Redes Aquí observamos que el primer segmento TCP envía los comandos para solicitar el archivo: 2do Cuatrimestre 2008 13 Trabajo Práctico N° 3 66.66 Seminario de Redes Luego si observamos los siguientes segmentos vemos que produce una secuencia: El servidor nos envía 5 segmentos de 1460 By luego uno de 892, y así se repite cíclicamente hasta terminar el ultimo fragmento que es de 336 By Ultimo segmento Deducimos que el servidor envía segmentos de 8 KBy que luego son fragmentados para pasar por la red ethernet, dichos fragmentos son de 1460 By como máximo ya que debemos sumar los 20 By de overhead de IP + 20 de TCP, o sea, los 1500 By de Ethernet. Si observamos el segundo segmento, donde el servidor nos envía el tamaño del archivo: Podemos calcular la velocidad aproximada de transferencia: 129024By/0.32s = 403 KB/s ò 3.22Mb/s Suponemos que la diferencia de velocidades se debe al error cometido en la captura de tiempos del wireshark. 2do Cuatrimestre 2008 14 Trabajo Práctico N° 3 66.66 Seminario de Redes Ahora probemos descargar dos archivos al mismo tiempo desde dos clientes distintos alojados en la misma PC con IP 192.168.1.101 Al realizar la conexión desde el segundo cliente el sistema nos provee el port 2305: Solicitamos el archivo Curr diego2.doc en ambos clientes: 2do Cuatrimestre 2008 15 Trabajo Práctico N° 3 66.66 Seminario de Redes Se observa un trafico similar al anterior pero esta vez se intercambian segmentos que van hacia la misma IP pero a distintos puertos TCP, o sea, a distintos procesos. Podemos observar en detalle las dos peticiones realizadas, una en el primer segmento y otra en el segmento 146: 2do Cuatrimestre 2008 16 Trabajo Práctico N° 3 66.66 Seminario de Redes Ahí se observa que la petición la realizan la IP origen 192.168.1.101 y los port origen son 2305 y 2294 dirigidos a 192.168.1.100 port 1200. Ahora probemos ver que pasa si se corta la comunicación mientras se hace la transferencia de información. 2do Cuatrimestre 2008 17 Trabajo Práctico N° 3 66.66 Seminario de Redes En este caso se corto definitivamente por error de time out. Veamos si podemos incidir en la cantidad de retransmisiones tapando la antena que nos conecta al router inalámbrico: 2do Cuatrimestre 2008 18 Trabajo Práctico N° 3 66.66 Seminario de Redes Aquí interrumpimos por unos dos segundos la transmisión y se observa que la solicitud del archivo (cliente a servidor) se retransmite por time out del ACK. Luego destapamos la antena y la comunicación fue exitosa. Ahora taparemos la antena por más tiempo hasta que se active el time out tantas veces como sea necesario para perder conexión: Se observan 5 retransmisiones en 15 segundos. Ahora hagamos esto pero intermitentemente para ver si bajan las ventanas de transmisión. 2do Cuatrimestre 2008 19 Trabajo Práctico N° 3 66.66 Seminario de Redes Observamos que el sistema operativo no implementa ningún control aunque hubo retransmisiones. 2do Cuatrimestre 2008 20 Trabajo Práctico N° 3 66.66 Seminario de Redes Diagramas de Flujo. Establecimiento de la Conexión Fin de la Conexión 2do Cuatrimestre 2008 21 Trabajo Práctico N° 3 66.66 Seminario de Redes Intercambio de Texto Intercambio de Comandos 2do Cuatrimestre 2008 22 Trabajo Práctico N° 3 66.66 Seminario de Redes Código fuente del cliente: Formulario: Declaración de variables: Dim Bytes As Long 'variable para guardar los bytes recibidos Dim Flag As Boolean Dim Flag2 As Boolean Dim lBytes As Long Dim lFileSize As Long Dim Nbytecmd As Long Función que se utiliza para comunicarme con el servidor remoto: Private Sub Command2_Click() ‘ command2 = conectar 'asignamos los datos de conexion Winsock1.RemoteHost = Text3.Text 2do Cuatrimestre 2008 ‘ text3 = servidor 23 Trabajo Práctico N° 3 66.66 Seminario de Redes Winsock1.RemotePort = Text4.Text ‘ text4 = port 'conectamos el socket Winsock1.Close Winsock1.Connect End Sub Función que envía el comando necesario para solicitar los nombres de los archivos que comparte el servidor: Private Sub Command4_Click() ‘ command4 = solicitar archivos compartidos Winsock1.SendData ("|Solicitud nombres de archivos|") End Sub Función que envía el comando necesario para solicitar un archivo seleccionado en text5: Private Sub Command5_Click() ‘ command5 = descargar archivo Winsock1.SendData ("|Solicitud de un archivo|" & Text5.Text) End Sub Evento que se produce cuando la conexión fue exitosa: 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 2do Cuatrimestre 2008 24 Trabajo Práctico N° 3 66.66 Seminario de Redes Evento que se produce cuando el servidor cierra la conexión: 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 Función que se utiliza para cerrar la conexión: Private Sub Command3_Click() ‘ command3 = Desconectar 'cerramos la conexión Winsock1.Close 'desplegamos un mensaje en la ventana Text1.Text = Text1.Text & "*** Conexión cerrada por el usuario." & vbCrLf 'desplazamos el scroll Text1.SelStart = Len(Text1.Text) End Sub 2do Cuatrimestre 2008 25 Trabajo Práctico N° 3 66.66 Seminario de Redes Función que se utiliza para enviar mensajes de texto al servidor: Private Sub Command1_Click() ‘ command1 = enviar 'enviamos el contenido de Text2, text2 esta a la izq. del botón enviar 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 Evento que se utiliza para procesar la información recibida desde el socket: Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) ‘ en el parametro bytesTotal se carga automaticamente la cantidad de bytes de datos del seg TCP Dim vData As String 'variable para guardar los datos recibidos Dim arrdata() As Byte Dim Buffer As String ' Preguntamos si lo que llegó es un archivo ???? If Flag = False Then Winsock1.GetData vData ' cargo todo lo que llegó en vData Buffer = vData If Mid(vData, 1, 9) = "|Archivo|" Then ‘ Mid se usa para indicar el prinsipio y el fin ‘dentro de un Array Flag = True Flag2 = True lBytes = 0 vData = Split(vData, "|") ' divide a vData en string: vData(0)=|Archivo| ' vData(1)= |tamaño del archivo| y vData(3)= |nombre del archivo| 2do Cuatrimestre 2008 26 Trabajo Práctico N° 3 lFileSize = vData(2) 66.66 Seminario de Redes ' capturamos el tamaño del archivo Nbytecmd = Len(vData(1)) + Len(vData(2)) + Len(vData(3)) + 4 'Nbytecmd es el Numero de bytes de comandos recibidos, 4 son los "|" arrdata = Mid(Buffer, Nbytecmd + 1, Len(Buffer)) ' Mid toma los bytes de buffer desde y hasta los dos parámetros que siguen ‘ Algoritmo para pasar de caracteres de 16 bits a caracteres de 1By For i = 0 To (Len(Buffer) - Nbytecmd - 1) arrdata(i) = arrdata(2 * i) Next ReDim arrdata(Len(Buffer) - Nbytecmd - 1) ‘ redimencionamos 'Creamos un archivo en modo binario, vData(3) es el nombre del archivo enviado ‘por el servidor Open App.Path & "\" & vData(3) For Binary Access Write As #1 ' abre un archivo en la ruta donde se encuentra la aplicación (App.Path) ' con el nombre vData(3) y lo aloja en RAM #1 End If End If If Flag Then ' Aumentamos lBytes con los datos que van llegando lBytes = lBytes + bytesTotal 'Recibimos los datos y lo almacenamos en el arry de bytes If Flag2 Then ' por unica vez no tomo los datos del socket porque ya lo hice antes ‘y ya le saque los cmd Put #1, , arrdata ‘ pasamos arrdata a la RAM Flag2 = False Else Winsock1.GetData arrdata ‘ en el resto de los segmentos TCP tomo los datos del ‘socket y los bajo a arrdata sin procesar arrdata Put #1, , arrdata End If 2do Cuatrimestre 2008 27 Trabajo Práctico N° 3 66.66 Seminario de Redes ' Si lo recibido es mayor o igual al tamaño entonces se terminó y cerramos 'el archivo abierto If ((lBytes - Nbytecmd) >= lFileSize) Then ' debemos descontar los bytes de cmd ‘ (Nbytecmd) 'Cerramos el archivo Close #1 'Reestablecemos el flag y la variable lBytes por si se intenta enviar otro archivo Flag = False lBytes = 0 'Mostrar mensaje de finalización MsgBox "El archivo se ha recibido por completo" End If End If '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 Text6.Text = Bytes + bytesTotal 'muestra los bytes recibidos desde que se 'inicio el socket 'acumulo los bytes recibidos en una variable global Bytes = Bytes + bytesTotal End Sub Evento que se produce cuando hay errores en el socket 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 2do Cuatrimestre 2008 28 Trabajo Práctico N° 3 66.66 Seminario de Redes Winsock1.Close 'mostramos informacion sobre el error MsgBox "Error numero " & Number & ": " & Description, vbCritical End Sub Código fuente del servidor: Función que se utiliza para dejar escuchando conexiones: Private Sub Command2_Click() ‘ command2 = Escuchar 'cerramos cualquier conexion previa Winsock1.Close 'asignamos el puerto local que abriremos 2do Cuatrimestre 2008 29 Trabajo Práctico N° 3 66.66 Seminario de Redes Winsock1.LocalPort = Text3.Text ‘ text3 = puerto '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 Función que se utiliza para cerrar la conexión: Private Sub Command3_Click() ‘ command3 = desconectar 'cierra la conexión Winsock1.Close 'desplegamos un mensaje en la ventana Text1.SelStart = Len(Text1.Text) Text1.Text = Text1.Text & "*** Conexión cerrada por el usuario." & vbCrLf Text1.SelStart = Len(Text1.Text) End Sub 2do Cuatrimestre 2008 30 Trabajo Práctico N° 3 66.66 Seminario de Redes Se usa la siguiente función para crear una búsqueda de la carpeta para compartir: Private Sub Command4_Click() ‘ command4 = buscar With Dir1 .Enabled = True .Visible = True End With End Sub Cuando se hace cambia el valor de la imagen que aparece para seleccionar capetas se ejecuta la siguiente función: Private Sub Dir1_Change() Text5 = Dir1.Path With Dir1 .Enabled = False .Visible = False .Refresh End With End Sub 2do Cuatrimestre 2008 31 Trabajo Práctico N° 3 66.66 Seminario de Redes Evento que se produce cuando se cierra el socket Private Sub Winsock1_Close() 'cierra la conexión Winsock1.Close 'desplegamos un mensaje en la ventana Text1.SelStart = Len(Text1.Text) Text1.Text = Text1.Text & "*** Conexión cerrada por el Cliente." & vbCrLf Text1.SelStart = Len(Text1.Text) End Sub ‘Evento que se produce cuando recibo archivos o comandos Private Sub Winsock2_DataArrival(index As Integer, ByVal bytesTotal As Long) Dim Buffer As String 'variable para guardar los datos Dim Archivos As String ' Nombre del archivo actual ' Dim Array_Archivos() As String Dim n As Long ' contador de archivos Dim sFileName As String Dim Ruta As String Dim Nombre_archivo As String 'obtenemos los datos y los guardamos en una variable Winsock2(index).GetData Buffer Text4.Text = Bytes + bytesTotal 'muestra los bytes recibidos Bytes = Bytes + bytesTotal 'acumula los bytes recibidos 2do Cuatrimestre 2008 32 Trabajo Práctico N° 3 66.66 Seminario de Redes '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 & "Socket:" & index & ">>Cliente >" & Buffer 'mostramos los datos Text1.SelStart = Len(Text1.Text) 'coloca el cursor al final del contenido ' Si el comando recibido es para solicitud de nombre de archivos disponibles en ' el servidor, entonces... If Mid(Buffer, 1, 31) = "|Solicitud nombres de archivos|" Then Archivos = Dir(Text5 & "\") Winsock2(index).SendData ("Archivos Compartidos:" & vbCrLf) 'Busca los demás Do While Len(Archivos) > 0 ' si la longitud de los archivos es mayor que cero => Existe n=n+1 'ReDim Preserve Array_Archivos(1 To n) ' Agrega el archivo al array ' Array_Archivos(n) = Archivos ' Sigue buscando Winsock2(index).SendData (Archivos & vbCrLf) 'envia la lista de archivos disponibles en la carpeta compartida Archivos = Dir$() ‘cargo en archivos los nombres de los archivos que contiene la carpeta Loop End If If Mid(Buffer, 1, 25) = "|Solicitud de un archivo|" Then Nombre_archivo = Mid(Buffer, 26, Len(Buffer) - 25) Ruta = Text5 & "\" & Nombre_archivo ‘ path completo del archivo Archivos = Dir(Text5 & "\") 2do Cuatrimestre 2008 33 Trabajo Práctico N° 3 66.66 Seminario de Redes Do While ((Nombre_archivo <> Archivos) And Len(Archivos) > 0) ‘Recorro toda la carpeta Archivos = Dir$() Loop If ((Nombre_archivo = Archivos) And (Nombre_archivo <> "")) Then 'sFileName = GetFileName(Ruta) ‘ invocamos a la funcion GetFileName 'Enviamos los datos (El tamaño, y el nombre) Winsock2(index).SendData ("|Archivo|" & FileLen(Ruta) & "|" & Nombre_archivo & "|") Dim Size As Long Dim arrData() As Byte Open Text5 & "\" & Nombre_archivo For Binary Access Read As #1 'Obtenemos el tamaño exacto en bytes del archivo para ' poder redimensionar el array de bytes Size = LOF(1) ReDim arrData(Size - 1) 'Leemos y almacenamos todo el fichero en el array Get #1, , arrData 'Cerramos Close 'Enviamos el archivo Winsock2(index).SendData (arrData) Else Winsock2(index).SendData ("El archivo: " & Nombre_archivo & " no existe" & vbCrLf) End If End If End Sub Función para manejo de errores en el socket: 2do Cuatrimestre 2008 34 Trabajo Práctico N° 3 66.66 Seminario de Redes 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 'Carga un nuevo socket al arreglo y devuelve su indice Función NuevoSocket para atender consultas en un port distinto al de escucha permanente (para aceptar conexiones recurrentes): NuevoSocket 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 2do Cuatrimestre 2008 35 Trabajo Práctico N° 3 66.66 Seminario de Redes 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 Evento que se produce cuando hay una solicitud de conexión desde una maquina remota 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 2do Cuatrimestre 2008 36 Trabajo Práctico N° 3 66.66 Seminario de Redes Text1.SelStart = Len(Text1.Text) Text1.Text = Text1.Text & "Sock" & numSocket & ":*** Conexion aceptada, listo para interactuar." & vbCrLf Text1.SelStart = Len(Text1.Text) End Sub Función que se utiliza para enviar mensajes de texto: 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 2do Cuatrimestre 2008 37 Trabajo Práctico N° 3 66.66 Seminario de Redes Text1.SelStart = Len(Text1.Text) 'coloca el cursor al final del contenido End If Next 'borramos Text2 Text2.Text = "" End Sub Función que se utiliza para obtener el nombre de un archivo dado el Path: Private Function GetFileName(sPath As String) Dim sBuffer As String * 255 Dim sTemp As String GetFileTitle sPath, sBuffer, Len(sBuffer) GetFileName = Left(sBuffer, InStr(1, sBuffer, Chr(0)) - 1) End Function 2do Cuatrimestre 2008 38 Trabajo Práctico N° 3 66.66 Seminario de Redes Conclusiones. Interfaz sencilla, clara y potente. Brinda métodos y eventos. Mismo objeto para “armar” clientes o servidores. 2do Cuatrimestre 2008 39
Puede agregar este documento a su colección de estudio (s)
Iniciar sesión Disponible sólo para usuarios autorizadosPuede agregar este documento a su lista guardada
Iniciar sesión Disponible sólo para usuarios autorizados(Para quejas, use otra forma )