Diferencia entre revisiones de «Xeración de servizos en rede con Java»

De MediaWiki
Ir a la navegación Ir a la búsqueda
()
Línea 183: Línea 183:
 
       int codResp = clienteFTP.getReplyCode();
 
       int codResp = clienteFTP.getReplyCode();
 
       if (!FTPReply.isPositiveCompletion(codResp)) {
 
       if (!FTPReply.isPositiveCompletion(codResp)) {
−
         System.out.printf(“ERROR: Conexión rechazada con cód. respuesta %d.\n”,
+
         System.out.printf(“ERROR: Conexión rechazada con cód. respuesta %d.\n”,codResp);
−
          codResp);
 
 
         System.exit(2);
 
         System.exit(2);
 
       }
 
       }
Línea 192: Línea 191:
 
         boolean loginOK = clienteFTP.login(usuario, password);
 
         boolean loginOK = clienteFTP.login(usuario, password);
 
         if (loginOK) {
 
         if (loginOK) {
−
           System.out.printf(“INFO: Login con usuario %s realizado.\n”,
+
           System.out.printf(“INFO: Login con usuario %s realizado.\n”,usuario);
−
            usuario);
 
 
         }
 
         }
 
         else {
 
         else {
−
           System.out.printf(“ERROR: Login con usuario %s rechazado.\n”,  
+
           System.out.printf(“ERROR: Login con usuario %s rechazado.\n”,usuario);
−
            usuario);
 
 
           return;
 
           return;
 
         }
 
         }
 
       }
 
       }
 
       System.out.printf(
 
       System.out.printf(
−
         “INFO: Conexión establecida, mensaje de bienvenida:\n====\
+
         “INFO: Conexión establecida, mensaje de bienvenida:\n====\n%s\n====\n”,clienteFTP.getReplyString());       
−
n%s\n====\n”,
+
       System.out.printf(“INFO: Directorio actual en servidor: %s, contenidos:\n”,clienteFTP.printWorkingDirectory());
−
       
 
−
clienteFTP.getReplyString());       
 
−
       System.out.printf(
 
−
        “INFO: Directorio actual en servidor: %s, contenidos:\n”,
 
−
        clienteFTP.printWorkingDirectory());
 
 
        
 
        
 
       FTPFile[] fichServ = clienteFTP.listFiles();
 
       FTPFile[] fichServ = clienteFTP.listFiles();
−
       for(FTPFile f: chServ) {
+
       for(FTPFile f: fichServ) {
 
         String infoAdicFich = “”;
 
         String infoAdicFich = “”;
 
         if(f.getType() == FTPFile.DIRECTORY_TYPE) {
 
         if(f.getType() == FTPFile.DIRECTORY_TYPE) {
Línea 225: Línea 217:
 
       e.printStackTrace();
 
       e.printStackTrace();
 
       return;
 
       return;
−
     } nally {
+
     } finally {
 
       if (clienteFTP != null) {
 
       if (clienteFTP != null) {
 
         try {
 
         try {

Revisión del 14:34 24 sep 2021

Clases de Java para comunicacións en rede

Na unidade didáctica anterior víronse clases de baixo nivel do paquete java.net da biblioteca estándar de clases de Java coas que se poden desenvolver aplicacións de cliente e de servidor de nivel de aplicación sobre os protocolos de nivel de transporte UDP e TCP.

Pódense utilizar estas clases para desenolver aplicacións de cliente para protocolos estándares de red tales coma FTP, POP3, etc; mais isto require dun conñecemento detallado do protocolo e ocuparse dos detalles do seu funcionamento interno. Para a maioría das aplicacións é suficiente (e resulta máis sinxelo) utilizar API ou bibliotecas de clases específicas para estes protocolos. Así pois veremos as API disponibles para os diferentes protocolos.

Clases de alto nivel del paquete estándar java.net

Ademáis das clases de baixo nivel, o paquete java.net da biblioteca estándar de clases de Java proporciona clases de alto nivel para protocolos estándares de nivel de aplicación.

Estas clases de alto nivel están baseadas na abstracción das URI ou URL, que designan e proporcionan acceso a unha grande variedade de recursos accesibles mediante diversos protocolos, coma por exemplo HTTP e FTP. O concepto de URL resulta familiar para calquiera que navegue por internet. As seguintes URL permiten obter un mesmo ficheiro de dous servidores diferentes e mediante dous protocolos diferentes (HTTP e FTP); basta con introducilas na barra de enderezos dun navegador web para iniciar a súa descarga:

NOTA. Nas últimas versións dos navegadores xa non é posible acceder mediante o protocolo FTP, por considerarse un protocolo inseguro. De momento aínda permiten o seu uso facendo cambios na configuración por defecto, pero é posible que en pouco tempo xa non sexa posible acceder a sitios FTP mediante o protocolo FTP dende o navegador. A solución pasará por usar un cliente FTP... ou utilizar protocolos máis seguros para a transferencia de ficheiros, coma pode ser scp.

Os recursos son secuencias de bytes e as clases da biblioteca estándar de clases de Java permiten designalos mediante unha URL. As clases de alto nivel de java.net permiten obter un InputStream para ler os contidos dun recurso designado mediante unha URL. Estas clases proporcionan un acceso sinxelo ós recursos de xeito uniforme e independente do protocolo.

Con todo, a funcionalidade destes protocolos vai máis alá do que ofrecen estas clases; para algunhas aplicacións pode ser necesario utilizar funcionalidades adicionais destes protocolos, e existen clases que o permiten.

Apache Commons Net

A biblioteca de clases Apache Commons Net inclúe clases de alto nivel clientes dos protocolos de rede estándares máis importantes.

A biblioteca de clases, a documentación y o código fonte están disponibles no ficheiro

commons-net-x.y-bin.tar.gz
x.y é a versión 

Este ficheiro comprimido contén varios ficheiros jar que a súa vez conteñen a biblioteca de clases, e os seus javadocs nun directorio api-docs (tamén accesibles na web). É relevante salientar entre as bibliotecas (libraries):

  • commons-net-x.y.jar
  • commons-net-examples-x.y.jar, con clases auxiliares útiles para algunhas aplicacións

Principales clases clientes de protocolos de Apache Commons Net

A xerarquía para as principais clases de Apache Commons Net clientes de protocolos son:

SocketClient
 +----- TelnetClient
 +----- FTP
 +        \----- FTPClient
 +                 \----- FTPSClient
 +----- TFTP
 +        \----- TFTPClient
 +----- POP3
 +        \----- POP3Client
 +                 \----- POP3SClient
 +----- SMTP
 +        \----- SMTPClient
 +                 \----- SMTPSClient
 +                          \----- AuthenticatingSMTPClient 
 +----- IMAP
 +        \----- IMAPClient
 +                 \----- IMAPSClient
 +                          \----- AuthenticatingIMAPClient
 +----- DaytimeTCPClient
 \----- TimeTCPClient
DatagramSocketClient
 +----- NTPUDPClient
 +----- DayTimeUDPClient
 \----- TimeUDPClient

En grosa están as clases clientes, que segue as seguintes regras xerais no referente á súa nomenclatura:

  • As clases que teñen o nombre dun protocolo (por exemplo, IMAP) teñen diversos métodos que corresponden a comandos do protocolo. Pódense utilizar para desenvolver aplicacións que interactúan co protocolo a baixo nivel, enviando comandos.
  • As clases fillas das anteriores, que teñen por nome o nome dun protocolo máis Client (por exemplo, POP3Client), son clases clientes do protocolo. Teñen métodos que permiten utilizar o protocolo a máis alto nivel.
  • As clases fillas das anteriores, que teñen o nome do protocolo + S + Client (por exemplo FTPSClient) son clases clientes do protocolo sobre unha capa de seguridade baseada en TLS/SSL.
  • As clases fillas das anteriores que comezan por Authenticating (por exemplo AuthenticatingIMAPClient ) teñen métodos que permiten a autenticación de clientes cos mecanismos que o protocolo correspondente proporciona para iso.

As clases Client de Apache Commons Net teñen métodos:

  • connect para a conexión cun servidor
  • login para o inicio dunha sesión co servidor
  • logout para terminar a sesión
  • disconnect para pechar a conexión

Outras bibliotecas de clases

O relevante protocolo SSH non conta con soporte das anteriores clases. A biblioteca de clases JSCH proporciona clases que se poden utilizar para desenvolver aplicacións clientes deste protocolo.

Comparativa de APIs

Resumidamente, para dar unha resposta sinxela á necesidade de uso dos protocolos estándares de rede máis habituales, cabe considerar as seguientes API.

APIs con clases clientes para diferentes protocolos estándares
API Protocolos
java.net HTTP HTTPS FTP FTPS
Apache Commons Net TELNET FTP FTPS POP3 POP3S SMTP SMTPS IMAP IMAPS NTP
JSCH SSH FTPS

Exemplos

Telnet

TelnetClientExample

Exemplo de uso de TelnetClient oficial de Apache Commons Net.

WeatherTelnet

Exemplo de uso trivial da clase TelnetClient.

Conecta ó servidor da Universdade de Michigan no porto 3000 (um-weather.sprl.umich.edu:3000) e permítelle o usuario interactuar co servidor vía entrada por teclado.

Telnet pasando servidor e porto como parámetro

Mesmo exemplo que o anterior, pero adaptado de xeito máis xenérico, permitindo acceder a un servidor (por ip ou nome de dominio) e portos específicados como parámetros de liña de comandos.

Con estes parámetros chámase o constructor da clase TelnetClient,que ten os métodos getOutputStream() e getInputStream() para obter os streams que permiten enviar e recibir información a e desde o socket.

Neste exemplo utilízase a clase auxiliar examples.util.IOUtil para enganchar entrada e saída estándares System.in e System.out a estes streams.

Psando como parámetros rainmaker.wunderground.com e 3000 este programa fai o mesmo que o programa de exemplo anterior.

 1 import java.io.IOException;
 2 import org.apache.commons.net.telnet.TelnetClient;
 3 import org.apache.commons.net.examples.util.IOUtil;
 4 public class ClienteTelnetGenerico {
 5   public static void main(String[] args) {
 6     if(args.length < 2) {
 7       System.out.println(“ERROR: indicar: servidor puerto”);
 8       System.exit(1);
 9     }
10     String servidor = args[0];
11     int puerto = Integer.parseInt(args[1]);
12     
13     TelnetClient telnet = new TelnetClient();
14     try {
15       telnet.connect(servidor, puerto);
16     } catch (IOException e) {
17       e.printStackTrace();
18       System.exit(2);
19     }
20     IOUtil.readWrite(telnet.getInputStream(), telnet.getOutputStream(),
21       System.in, System.out);
22     try {
23       telnet.disconnect();
24     } catch (IOException e) {
25       e.printStackTrace();
26       System.exit(3);
27     }
28   }
29 }

FTP

FTPClientExample

Exemplo de uso que permite súbdas, baixadas,etc. sobre FTP, FTPS e FTP sobre HTTP.

ServerToServerFTP

Exemplo de uso que permite a transferencia dun ficheiro de servidor a servidor (de host1 a host2)

TFTPExample

Exemplo de uso de un cliente tfrp (trivial ftp é un protocolo distinto a ftp)

El siguiente programa se conecta a un servidor de FTP y proporciona una lista de los cheros y directorios disponibles. A este programa se le pasa como parámetro de línea de comandos un servidor, que se puede dar como una dirección IP o como un nombre de dominio.

También se puede pasar un usuario y una contraseña. Se intenta establecer el modo pasivo con clienteFTP.enterLocalPassiveMode() . El servidor podría no soportar este modo, aunque esto es poco usual. Se establece el modo binario con clienteFTP.setFileType(FTP. BINARY_FILE_TYPE). Se puede utilizar este programa para conectarse a un servidor de FTP público que permita conexión anónima, como, por ejemplo, ftp.rediris.es. También para conectar a un servidor privado, con un nombre de usuario y contraseña. Por ejemplo, el puesto en marcha según las instrucciones proporcionadas en un recurso digital anterior. En cuanto al tratamiento de errores, es de reseñar que, tras cualquier error, una vez establecida la conexión, se sale con return , con lo que se ejecuta el bloque finally , que cierra la conexión.

 1 package listaficherosftp;
 2 import java.io.IOException;
 3 import org.apache.commons.net.ftp.FTPClient;
 4 import org.apache.commons.net.ftp.FTPReply;
 5 import org.apache.commons.net.ftp.FTPFile;
 6 import org.apache.commons.net.ftp.FTP;
 7 
 8 public class ListaFicherosFTP {
 9   public static void main(String[] args) {
10     if (args.length < 1) {
11       System.out.println(“ERROR: indicar como parámetros:”);
12        System.out.println(“servidor usuario(opcional) contraseña(opcional)”);
13       System.exit(1);
14     }
15     String servidorFTP = args[0];
16     String usuario = “anonymous”, password = “”;
17     if (args.length >= 2) {
18       usuario = args[1];
19     }
20     if (args.length >= 3) {
21       password = args[2];
22     }
23     FTPClient clienteFTP = new FTPClient();
24     try {
25       clienteFTP.connect(servidorFTP);
26       int codResp = clienteFTP.getReplyCode();
27       if (!FTPReply.isPositiveCompletion(codResp)) {
28          System.out.printf(“ERROR: Conexión rechazada con cód. respuesta %d.\n”,codResp);
29         System.exit(2);
30       }
31       clienteFTP.enterLocalPassiveMode();
32       clienteFTP.setFileType(FTP.BINARY_FILE_TYPE);
33       if (usuario != null && password != null) {
34         boolean loginOK = clienteFTP.login(usuario, password);
35         if (loginOK) {
36           System.out.printf(“INFO: Login con usuario %s realizado.\n”,usuario);
37         }
38         else {
39           System.out.printf(“ERROR: Login con usuario %s rechazado.\n”,usuario);
40           return;
41         }
42       }
43       System.out.printf(
44          “INFO: Conexión establecida, mensaje de bienvenida:\n====\n%s\n====\n”,clienteFTP.getReplyString());      
45       System.out.printf(“INFO: Directorio actual en servidor: %s, contenidos:\n”,clienteFTP.printWorkingDirectory());
46       
47       FTPFile[] fichServ = clienteFTP.listFiles();
48       for(FTPFile f: fichServ) {
49         String infoAdicFich = “”;
50         if(f.getType() == FTPFile.DIRECTORY_TYPE) {
51           infoAdicFich = “/”;
52         }
53         else if(f.getType() == FTPFile.SYMBOLIC_LINK_TYPE) {
54           infoAdicFich = “ -> “ + f.getLink();          
55         }
56         System.out.printf(“%s%s\n”, f.getName(), infoAdicFich);
57       }
58     } catch (IOException e) {
59       System.out.println(“ERROR: conectando al servidor”);
60       e.printStackTrace();
61       return;
62     } finally {
63       if (clienteFTP != null) {
64         try {
65           clienteFTP.disconnect();
66           System.out.println(“INFO: conexión cerrada.”);
67         } catch (IOException e) {
68           System.out.println(“AVISO: no se pudo cerrar la conexión.”);
69         }
70       }
71     }
72   }
73 }

Créditos e referencias

Apache Commons