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:

ftp.jpg
Figure 1: Protocolo FTP

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:

http.jpg
Figure 2: Protocolo HTTP

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


© 2024 Santiago Faci y Fernando Valdeón