Tabla de Contenidos
Programación de servicios de red
FTP
FTP (File Transfer Protocol) es un protocolo de transferencia de ficheros entre un cliente y un servidor. Básicamente se utilizar para subir/bajar ficheros a/desde un sitio remoto. Sus características principales son las siguientes:
- El lado servidor utiliza el puerto 21 para establecer su conexión
- Incorpora mecanismo de autenticación (usuario/contraseña) y soporte para usuarios anónimos (sólo lectura) y también existen versiones que soportan conexiones seguras utilizando el protocolor HTTPS
- También incorpora mecanismos de seguridad basada en permisos
- Permite navegar por el sitio remoto y realizar en él algunas acciones como crear, listar, eliminar directorios, copia de ficheros, . . . a través de comandos (mkdir, ls, rmdir, . . .)
- Es posible realizar implementaciones de clientes con interfaz gráfica por lo que el manejo puede llegar a ser muy intuitivo
- Es un protocolo cliente/servidor de forma que una máquina ejecuta el lado servidor almacenando los ficheros, de forma que los clientes pueden conectarse a él para descargarse esos ficheros o bien (si tienen permisos) pueden subir nuevos ficheros
- Es uno de los protocolos más antiguos de Internet pero sigue siendo ampliamente utilizado
A continuación se muestran ejemplos de código para implementar un cliente y un servidor FTP, utilizando la librería Apache MINA FtpServer
Cliente FTP
Cómo establecer una conexión
. . . FTPClient clienteFtp = new FTPClient(); clienteFtp.connect(IP, PUERTO); clienteFtp.login(USUARIO, CONTRASENA); /* * En el modo pasivo es siempre el cliente quien abre las conexiones * Da menos problemas si estamos detras de un firewall, por ejemplo */ clienteFtp.enterLocalPassiveMode(); clienteFtp.setFileType(FTPClient.BINARY_FILE_TYPE); . . .
Cómo descargar un fichero
. . . // Lista los ficheros del servidor (a modo de ejemplo) FTPFile[] ficheros = clienteFtp.listFiles(); for (int i = 0; i < ficheros.length; i++) { System.out.println(ficheros[i].getName()); } // Fija los ficheros remoto y local String ficheroRemoto = "/modelo.txt"; File ficheroLocal = new File("modelo.txt"); System.out.println("Descargando fichero '" + ficheroRemoto + "' del servidor . . ."); // Descarga un fichero del servidor FTP OutputStream os = new BufferedOutputStream(new FileOutputStream(ficheroLocal)); if (clienteFtp.retrieveFile(ficheroRemoto, os)) System.out.println("El fichero se ha recibido correctamente"); os.close(); . . .
Servidor FTP
El servidor
. . . FtpServerFactory serverFactory = new FtpServerFactory(); ListenerFactory miListenerFactory = new ListenerFactory(); miListenerFactory.setPort(PUERTO); serverFactory.addListener("default", miListenerFactory.createListener()); try { ConnectionConfigFactory miConnectionConfigFactory = new ConnectionConfigFactory(); miConnectionConfigFactory.setAnonymousLoginEnabled(true); ConnectionConfig connectionConfig = miConnectionConfigFactory.createConnectionConfig(); serverFactory.setConnectionConfig(connectionConfig); // Fija la configuracion de las cuentas de usuario PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); userManagerFactory.setFile(new File("usuarios.properties")); serverFactory.setUserManager(userManagerFactory.createUserManager()); FtpServer servidorFtp = serverFactory.createServer(); servidorFtp.start(); } catch ( . . . ) { . . . } ...
Fichero de configuración
# Password: "admin" # Username: "admin" ftpserver.user.admin.userpassword=21232F297A57A5A743894A0E4A801FC3 ftpserver.user.admin.homedirectory=./home ftpserver.user.admin.enableflag=true ftpserver.user.admin.writepermission=true ftpserver.user.admin.maxloginnumber=0 ftpserver.user.admin.maxloginperip=0 ftpserver.user.admin.idletime=0 ftpserver.user.admin.uploadrate=0 ftpserver.user.admin.downloadrate=0
HTTP
HTTP es un protocolo utilizado para la transferencia de hipertexto (páginas web) a través de la red (normalmente Internet). El hipertexto es un sistema de documentos (de texto) en el que éstos no están organizados de forma secuencial sino que es posible acceder a cualquiera de ellos desde cualquier otro, incluso si éstos provienen de diferentes fuentes (sitios web), mediante lo que se conoce como un hipervínculo. Sus características principales son las siguientes:
- Los servidores HTTP (o servidores web) utilizan el puerto 80 para establecer su conexión
- El lenguaje utilizado para crear los documentos (o páginas web) es el HTML
- Permiten además la transferencia de cualquier otro tipo de ficheros
- El protocolo por sí solo no establece mecanismos de seguridad, por lo que en un principio cualquier puede acceder al documento que quiera. Más adelante se han implementando herramientas que permiten añadir esa capa de seguridad donde se requiere
- Es un protocolo cliente/servidor en el que un servidor almacena una serie de documentos de forma que múltiples clientes pueden conectarse a él para acceder a los mismos
- Es un protocolo muy sencillo y antiguo y, probablemente, el más extendido y utilizado en Internet
Cliente HTTP (navegador web)
Para implementar un cliente HTTP basta con fijar una URL a un componente JEditorPane
, puesto que es capaz de renderizar páginas web HTML directamente (aunque se una forma bastante básica).
. . . JEditorPane epPagina = new JEditorPane(); String url = "http://psp.abrilcode.com"; try { epPagina.setPage(url); } catch (IOException ioe) { // Error al intentar cargar la URL } } . . .
Servidor HTTP (servidor web)
En este caso implementamos directamente la versión multihilo del servidor HTTP. Así, de forma similar como hicimos con el servidor echo, en una clase principal esperamos las conexiones de clientes de forma que sean atendidos mediante hilos que serán lanzados por cada una de las conexiones recibidas.
. . . boolean conectado = true; ServerSocket servidor = null; try { servidor = new ServerSocket(80); while (conectado) { ConexionCliente conexionCliente = new ConexionCliente(servidor.accept()); conexionCliente.start(); } if (servidor != null) servidor.close(); } catch ( . . . ) { . . . } . . .
Ya en la clase ConexionCliente
será donde analicemos la petición recibida para comprobar que documento HTML nos ha solicitado el cliente.
. . . @Override public void run() { try { String peticion = entrada.readLine(); if (peticion.startsWith("GET")) { String[] partes = peticion.split(" "); String rutaFichero = partes[1].substring(1); /* Si no ha solicitado ninguna pagina es que ha solicitado la * pagina por defecto que normalmente es index.html */ if (rutaFichero.equals("")) rutaFichero = "index.html"; File fichero = new File("htdocs" + File.separator + rutaFichero); if (!fichero.exists()) { salida.writeBytes("HTTP/1.0 404 Not Found\r\n"); salida.writeBytes("\r\n"); salida.writeBytes("<html><body>Documento no encontrado</body></html >\r\n"); desconectar(); return; } else { . . . } } } } . . .
En el caso de que la petición prospere, habrá que preparar la respuesta, que estará compuesta de cierta información de protocolo más el contenido del documento solicitado.
. . . // Prepara el fichero que se tiene que enviar FileInputStream fis = new FileInputStream(fichero); int tamanoFichero = (int) fichero.length(); byte[] bytes = new byte[tamanoFichero]; fis.read(bytes); fis.close(); // Prepara las cabecera de salida para el navegador salida.writeBytes("HTTP/1.0 200 OK\r\n"); salida.writeBytes("Server: MiJavaHTTPServer\r\n"); if (rutaFichero.endsWith(".jpg")) salida.writeBytes("Content -Type: image/jpg\r\n"); else if (rutaFichero.endsWith(".html")) salida.writeBytes("Content -Type: text/html\r\n"); salida.writeBytes("Content -Length: " + tamanoFichero + "\r\n"); // Linea en blanco, obligatoria segun el protocolo salida.writeBytes("\r\n"); // Envia el contenido del fichero salida.write(bytes, 0, tamanoFichero); desconectar(); . . .
Servicios de red
Proyectos de Ejemplo
Los proyectos de los ejercicios que se vayan haciendo en clase estarán disponibles en el repositorio psp-ejercicios de BitBucket
Prácticas
- Práctica 3.1 Creación de un Servicio de red
© 2024 Santiago Faci y Fernando Valdeón