Java proporciona el paquete java.net para facilitar el trabajo de programación relacionado con internet y con intranets (redes locales que funcionan con el protocolo de internet). En esta lección estudiaremos varias clases del paquete java.net:
Direcciones IP
La clase InetAddress proporciona métodos para obtener la dirección IP del propio ordenador o de cualquier otro conectado a internet o a la misma intranet. Lo primero se hace con el método estático:
static public InetAddress getLocalHost()
Lo segundo se hace con el método estático:
static public InetAddress getByName(String host)
que puede usarse dando el nombre de un ordenador o bien su dirección IP. En ambos casos el método consulta a un servidor DNS (Domain Name Server) para obtener la dirección IP en el primer caso o el nombre del ordenador en el segundo.
Un objeto de la clase InetAddress tiene dos datos importantes de una dirección de internet: el nombre del ordenador y la dirección IP. El primero se obtiene mediante el método public String getHost() y el segundo mediante cualquiera de los métodos public String getHostAddress() o public byte[] getAddress(). (Éste último devuelve la dirección en un vector de cuatro bytes que son los cuatro números entre 0 y 255 de la dirección IP).
El programa unidad09.dirinet utiliza estos métodos primero para obtener los datos del servidor local (localhost) y luego para obtener los datos del servidor que se le pasa como parámetro. La imagen siguiente es el resultado de cuatro llamadas a este programa con diferentes parámetros.
De la primera llamada se puede deducir que el ordenador en que se ejecutó el programa se llama AMB-JLA y tiene la dirección IP=192.168.0.101. La segunda llamada muestra el servidor local por defecto llamado localhost tiene dirección IP=127.0.0.1 (esto es así en casi todos los ordenadores). La tercera llamada muestra que la dirección IP del servidor web llamado www.cnice.mecd.es es 195.53.123.85. La cuarta llamada muestra que esa misma dirección IP, cuando se usa en un proceso inverso para obtener el nombre del servidor, proporciona un nombre diferente: web1.cnice.mecd.es. El lector puede comprobar que funciona igual que el otro nombre si se usa en un navegador de internet, es decir que el ordenador con la dirección IP=195.53.123.85 tiene al menos dos nombres diferentes.
Los resultados de estas llamadas son diferentes si el ordenador no está conectado a una red local o a internet. Por ejemplo si no está conectado a una red local la dirección IP de AMB-JLA resulta ser 127.0.0.1 (la misma que localhost) y si tampoco está conectado a internet las direcciones de otros ordenadores no se pueden obtener, de hecho el programa lanza una excepción en ese caso.
Este el código del programa unidad09.dirinet.
Los datagramas IP o simplemente datagramas, son los paquetes mínimos de información que se envían por las redes o por internet. Son los elementos básicos del "Internet Protocol" (IP) o protocolo de internet. El paquete java.net proporciona dos clases: DatagramPacket y DatagramSocket que ponen en manos del programador de Java toda la fuerza del protocolo de internet con las que se pueden desarrollar programas que se comuniquen entre sí a través de internet, a través de una red local o en un mismo ordenador. Una de las ventajas de este sistema de comunicación es que funciona igualmente entre dos ordenadores lejanos o cercanos e incluso en un mismo ordenador. El programador de Java no necesita conocer en detalle el protocolo IP (Internet Protocol) y la estructura de los paquetes de información que se envían por las redes, sólo necesita saber cómo crearlos, enviarlos a su destino, recibirlos y extraerles la información. Todas estas operaciones pueden lograrse usando las clases: DatagramPacket. y DatagramSocket.
Para ilustrar este sistema de comunicación presentamos un sencillo programa de de conversación por escrito (lo que se llama un "chat") que puede usarse entre dos ordenadores cualesquiera conectados a una red o a internet. El programa se llama unidad09.chat. Para utilizarlo hay que echar a andar dos copias del programa en dos ordenadores conectados a internet o a una misma red (también pueden arrancarse las dos copias en un mismo ordenador, pero en este caso se pierde un poco el sentido del programa). El programa presenta este aspecto:
En el campo destino debe escribirse el nombre o la dirección IP de un ordenador que esté en la misma red local o en internet y en el que también se esté ejecutando el programa. El puerto en principio no debe cambiarse pues ambos lados deben usar el mismo puerto. Para mandar un mensaje basta escribirlo en el campo de texto mensaje y dar <intro> o pulsar el botón enviar. El destinatario deberá recibir el mensaje (aparecerá en cuadro de texto de la parte inferior) y podrá contestarlo haciendo lo mismo. Los mensajes enviados también se registran en el cuadro de texto inferior.
Este es el código del programa unidad09.chat:
El alumno debe estudiar principalmente los métodos send() y run() donde se encuentran los códigos encargados de enviar los mensajes y de recibirlos, respectivamente. Observará que el método que recibe los datagramas: receive(DatagramPacket) se llama dentro de un hilo diferente al de la interfaz gráfica para que pueda esperar los mensajes sin impedir que el usuario puede escribir los suyos. También observará que para recibir datagramas escucha en un puerto específico (al que se están enviando los datagramas) pero en cambio no se especifica el puerto del DatagramSocket que envía los datagramas sino que se deja libre. De hecho no se puede usar el mismo puerto porque éste se encuentra ocupado esperando recibir datagramas.
Aunque este programa es muy simple y permite enviar cada mensaje a un solo destino, tiene los elementos básicos de un programa de conversación.
Sin embargo el empleo de datagramas impone varias limitaciones. La más importante es que el envío de datagramas es inseguro, es decir, no se tiene nunca la certeza de que un datagrama haya llegado a su destino ni del orden en que han de llegar los diversos datagramas enviados. Esto unido al hecho de que el tamaño de un datagrama está limitado (por ejemplo a 1500 bytes en las redes Ethernet), hace que este sistema de comunicación sea insuficiente para las necesidades de las comunicaciones modernas. Para ello se deben emplear los enchufes, conexiones o sockets que ofrecen todas las ventajas de que los datagramas carecen. Vale la pena sin embargo remarcar que los sockets se implementan a base de datagramas, o sea que se trata de una herramienta de más alto nivel, más segura y más flexible pero basada en las misma herramientas básicas de bajo nivel.
La comunicación realizada sólo con datagramas no es confiable. En cambio la comunicación con sockets sí es confiable y se llama "Transmission Control Protocol" o TCP que significa protocolo de control de transmisión. Antes de hablar de los sockets presentamos una breve explicación de cómo funciona internet y los protocolos IP y TCP/IP.
Los protocolos IP y TCP fueron desarrollados por el Departmento de Defensa de EEUU (el Pentágono) para conectar redes de ordenadores diseñados por diferentes proveedores y formar una red única: Internet. El software de IP proporciona un mecanismo para enviar información dentro de una misma red y a la internet global. El diseño del protocolo IP permite que la comunicación funcione aunque algunos de los ordenadores conectados a la red fallen. Este diseño ha permitido la construcción de redes muy grandes sin necesidad de que exista un ordenador central que controle su funcionamiento.
El protocolo de comunicación de Internet TCP/IP está formado por capas:
El alumno puede consultar www.ietf.org/ para cualquier información que desee sobre protocolos de internet.
También se le recomienda consultar la Connected: An Internet Encyclopedia en:
http://www.freesoft.org/CIE/index.htm
y en particular:
http://www.freesoft.org/CIE/Topics/
para cualquier tema que le interese sobre la historia o los protocolos de internet.
Los Sockets - son los objetos (programas) que implementan el protocolo TCP/IP y realizan una comunicación confiable entre dos ordenadores de la red de redes de una manera cómoda y simple.
La manera de utilizar los enchufes o sockets es muy sencilla. Hay dos tipos de enchufes o sockets representados en Java por las clases: ServerSocket y Socket. Los ServerSockets esperan a que un cliente se conecte a ellos y aceptan la conexión que se materializa en un socket normal. Los sockets normales también se pueden crear directamente dando el nombre del ordenador al que se desea conectar y el puerto que se desea utilizar. De un socket cualquiera ya sea obtenido a través del método accept() de un ServerSocket o creado directamente, se pueden obtener corrientes de entrada y salida con getInputStream() y getOutputStream() y a través de ellas mantener una comunicación continua de ida y vuelta. La idea es tan sencilla como la de los datagramas, pero sin que el programador se entere los sockets realizan un trabajo complejo enviando y recibiendo datagramas, ordenándolos al recibirlos en el orden en que fueron enviados y asegurándose de que ninguno se pierde pues mantienen una comunicación bilateral hasta asegurarse que la información ha llegado completa a su destino. Sería muy complicado explicar en detalle el trabajo que realizan los sockets pero afortunadamente no es necesario y como el resultado final es también muy claro y simple, el programador de Java puede usar los sockets con mucha facilidad y confianza para sus programas de comunicación.
Como primer ejemplo de uso de los sockets presentamos otro programa de conversación o chat que es ya un programa cliente-servidor y al que se pueden conectar simultáneamente varios clientes para conversar. Este chat consta de dos programas: chatServer y chatClient. Para usar el chat es necesario arrancar
java unidad09.chatServer
en un ordenador de una red y arrancar luego en otros ordenadores varias copias del cliente con
java unidad09.chatClient <login>
utilizando diferentes logins. Cada vez que se abre un chatClient, éste abre un socket al servidor, el servidor acepta la conexión y la pone en una lista de conexiones que trabajan simultáneamente escuchando mensajes de los clientes y transmitiendo a todos los clientes conectados cada mensaje recibido. Para enviar un mensaje desde un cliente basta escribir unas palabras en la línea de comandos y pulsar <intro>. En la consola de cada cliente aparecen los mensajes escritos por todos los clientes.
Hé aquí la imagen de la consola en una sesión de chatClient:
Para cerrar chatClient basta enviar un mensaje vacío. Para cerrar chatServer basta dar un <intro>.
Este es el código de chatServer:
Este es el código de chatClient:
El alumno debe estudiar detenidamente estos dos programas que ofrecen un ejemplo general y poderoso de un programa cliente-servidor. Estudie el código de chatServer.java y chatClient.java buscando especialmente cómo se abre el ServerSocket en chatServer y los Sockets en chatClient y cómo de los sockets se construyen Streams, Readers y Writers para realizar la comunicación. Preste también especial atención a los hilos del servidor y del cliente. Observe que dentro de chatServer.java existe otra clase llamada chatConnection que se usa para representar cada una de las conexiones de un cliente al servidor y hay otra clase llamada Quiter que se encarga de cerrar el proceso cuando en la ventana del servidor se pulsa <intro>. Observe cómo el servidor lleva control de todos los clientes activos para enviarles (método broadcast) los mensajes de cualquiera de ellos. En chatClient debe prestar especial atención a cómo el programa controla separadamente en dos hilos diferentes la recepción y el envío de mensajes.
El estudiante debe estudiar este ejemplo con detenimiento. Se trata de un ejemplo sencillo pero completo de lo que se conoce como programa cliente-servidor. El uso de hilos, sockets y streams es imprescindible para lograr este tipo de comunicación.
Hay varios sistemas de comunicación estándar que utilizan el protocolo TCP/IP, es decir, los sockets. Los ejemplos más importantes son el correo electrónico y los servidores de páginas web. Estos sistemas utilizan protocolos especiales de comunicación construidos sobre TCP/IP como son el SMTP (Simple Mail Transfer Protocol) del correo electrónico y el HTTP (HyperText Transfer Protocol) de los servidores de páginas Web.
En esta sección presentamos la clase Mail que hace una implementación sencilla del protocolo SMTP de correo electrónico. El programa enviarEMail usa esta clase para ofrecer la posibilidad de enviar e-mails si se tiene un servidor smtp al que se tiene derecho de acceder. La imagen representa una sesión con este programa:
Los alumnos deben ejecutar el programa con la llamada:
java unidad09.enviarEMail
y hacer la prueba de enviar algunos mensajes usando su propio servidor smtp y su propia dirección de correo.
Este es el código de la clase Mail:
Esta clase implementa la parte básica del protocolo SMTP que consiste en los siguientes pasos, como puede comprobar el alumno estudiando el código de Mail:
La referencia oficial del protocolo smtp es: http://www.ietf.org/rfc/rfc0821.txt . y puede consultarse en formato html en http://www.freesoft.org/CIE/RFC/821/index.htm .
Éste es el código del programa enviarEMail:
En realidad es sólo una interfaz de usuario simple para utilizar la clase Mail.
Sin duda lo que más se usa hoy en día de internet el la World Wide Web (WWW) que no es otra cosa que los servidores de páginas web. ¿Qué es un servidor de páginas web? Es un programa que espera peticiones de servicio en un puerto (normalmente el puerto 80) y responde a ellas.La mayoría de las peticiones de servicio consisten en el envío de archivos al cliente. El protocolo de comunicación de la WWW se llama HTTP (HyperText Transfer Protocol) y abarca muchos detalles. Sin embargo no es difícil implementar un servidor sencillo que responda sólo a las peticiones de archivos. En esta sección presentamos tal servidor.
Para arrancarlo basta hacer la llamada:
java unidad09.HTTPServer [<base>]
donde el parámetro opcional <base> debe ser un subdirectorio donde se encuentran los archivos que se quieren ofrecer a los clientes de nuestro servidor HTTPServer. Si no se escribe un parámetro <base> entonces el programa toma como directorio base aquel desde el que se arracó el programa. En particular si el curso Java Intemedio se encuentra por ejemplo en c:/CursoJava/java_intemedio entonces arrancar HTTPServer sin parámetro es equivalente a arrancarlo con esta llamada:
java unidad09.HTTPServer c:/CursoJava/java_profundizacion
El programa responde dando el mensaje:
HTTPServer <nombre> escuchando en el puerto
80
WEB ROOT = c:\CursoJava\java_profundizacion\
Press <return> to close server.
Si estando activo el HTTPServer arrancamos nuestro navegador de internet y pedimos que abra el URL http://localhost/index.htm veremos aparecer el índice del curso Java Profundización y en la consola del servidor veremos:
HTTPServer no es un servidor HTTP completo, pero tiene toda la funcionalidad necesaria para enviar al cliente todos los archivos del curso, por lo cual podremos navegar normalmente por todas las unidades del curso. Si además nuestro ordenador está conectado a una red local y tiene por ejemplo el nombre <mi_ordenador> entonces desde cualquier ordenadpr de la red podremos acceder a los archivos del curso Java Intermendio usando la dirección http://<mi_ordenador>/index.htm.
Al navegar veremos aparecer en la consola los nombres de todas las páginas, imágenes, classes de Java, archivos .java, etc... que el navegador pide al servidor y que éste le envía.
Este es código de HTTPServer:
El alumno puede comprobar que se trata de un programa aún más sencillo que chatServer de una sección anterior. Igual que chatServer, lo que hace es abrir un ServerSocket, en este caso en el puerto 80, y esperar clientes. Cuando un cliente se conecta crea un socket y un objeto de la clase HTTPConnection, que trabaja en un hilo independiente, para comunicarse con él. HTTPConnection se encarga exclusivamente de atender a ese cliente. Para ello lee la petición y la procesa. Es en este punto donde el servidor es modesto pues se limita a procesar las peticiones de tipo GET y sólo las que corresponden a archivos con extensiones htm, html, jpg, gif, txt, java, class, jar y zip. Esto se decide en el método getMimeType(File f). Cualquier otro tipo de archivo se considera "prohibido" y para cualquier solicitud de servicio que no sea un GET se responde con el mensaje "501 Not Implemented".
Nuestro HTTPServer sólo utiliza los siguientes códigos de respuesta:
código | mensaje | explicación |
200 | OK | Solicitud aceptada, el servidor enviará lo que el cliente pidió. |
400 | Bad Request | Hubo un error de sintaxis en la solicitud. |
403 | Access Forbidden | El servidor no permite accesar el archivo solicitado. |
404 | Not Found | El servidor no encuentra el archivo solicitado. |
415 | Unsupported Media Type | No se sirven archivos de este tipo. |
500 | Internal Server Error | Se produjo un error al antender la solicitud. |
501 | Not Supported | El servidor no ofrece este servicio. |
El protocolo HTTP contempla otros servicios aparte de GET y tiene muchos más códigos de respuesta. Un servidor HTTP completo debe implementar los otros servicios que especifica el protocolo HTTP (como POST, PUT y HEAD), ofrecer más tipos (MIME) de archivos que los que ofrece el nuestro e investigar más a fondo el tipo de archivo, no solamente basarse en su extensión. Además hay una serie de detalles posibles que debe atender de una solicitud. En una solicitud GET típica además del archivo solicitado el cliente puede especificar qué tipos de archivo MIME prefiere o acepta, fechas de caducidad, si piensa hacer más solicitudes de inmediato, etc y el servidor puede enviar más información sobre los archivos que envía como por ejemplo la fecha de su última actualización y alguna información más sobre sí mismo.
Si el alumno está interesado en los detalles del protocolo HTTP puede consultar por ejemplo el libro:
Webmaster in a Nutshell de Stephen Spainhour y Robert Eckstein, editorial O'Reilly.
y la página http://www.freesoft.org/CIE/RFC/2068/index.htm de la enciclopedia Connected.
El sitio oficial del protocolo HTTP es www.w3.org/Protocols/. Y en particular ftp://ftp.isi.edu/in-notes/rfc2616.txt es el documento oficial del protocolo HTTP/1.1.
Las siglas URL vienen del inglés Uniform Resource Locator que significa localizador uniforme de un recurso. Se trata de un instrumento para localizar cualquier recurso (archivo de texto, imagen, applet, etc...) en internet. En general un URL consta de un esquema y una parte específica para el esquema y puede representarse como una cadena de texto. Los esquemas más usados son los que corresponden a los protocolos http, file y ftp pero hay otros como gopher, mailto, news, nntp, telnet y puede haber otros en el futuro.
La parte específica para el esquema http consiste de a) protocolo, b) servidor c) puerto d) archivo y e) parámetros. Un URL con esquema http se escribe así:
http://servidor:puerto/archivo?parámetros
El puerto suele omitirse (con lo que adquiere el valor 80 por defecto) y muchas veces no hay parámetros por lo cual la forma más común de un URL con esquema http es:
http://servidor/archivo
donde archivo puede incluir varios subdirectorios antes de lo que es propiamente el archivo y además puede incluir una referencia como por ejemplo unidad09.htm#url donde url es la referencia dentro del archivo.
La parte específica para el esquema file consiste de a) protocolo b)servidor y c) archivo. Un URL con esquema file se escribe así:
file://servidor/unidad:/archivo
Si la parte del servidor es vacía entonces se obtiene la típica forma de un URL con esquema file en el propio ordenador:
file:///C:/archivo
donde otra vez, archivo puede incluir varios subdirectorios separados por / antes de lo que es propiamente el archivo.
Es importante estar consciente de que la especificación de los URL para archivos, es decir los de esquema file, no coincide con la especificación de un archivo en el sistema operativo Windows ni en otros sistemas operativos. Por ejemplo el equivalente en Windows a file:///C:/archivo es C:\archivo donde dentro de archivo deben sustituirse las diagonales / por diagonales invertidas \ . Este hecho es motivo de confusión frecuente.
Los protocolos que requieren usuario y contraseña usan la siguiente forma:
//usuario:contraseña@servidor:puerto/archivo
En particular el URL de una sesión ftp tiene la forma:
ftp://usuario:contraseña@servidor:puerto/archivo
Para más detalles sobre estos y otros esquemas de URL's puede consultar:
http://www.freesoft.org/CIE/RFC/1738/index.htm
Java ofrece la clase URL específica para el manejo de URL's. La clase ofrece varios constructores:
public URL(String spec) throws MalformedURLException;
public URL(String protocol,String host,String file) throws MalformedURLException;
public URL(String protocol,String host,int port,String file) throws MalformedURLException;
public URL(URL context,String spec) throws MalformedURLException;
Para usar el primero hay que escribir la forma completa del URL (en el caso de un http se hace igual que en un navegador). Por ejemplo:
new URL("http://www.cnice.mecd.es/enlaces/index.html");
es una construcción de un URL usando el primer constructor. Para crear el mismo URL usando el segundo constructor habría que hacer esta llamada:
new URL("http","www.cnice.mecd.es","/enlaces/index.html");
Observe que el tercer constructor requiere el puerto, en los otros constructores el puerto se toma como el puerto por defecto correspondiente al protocolo (para http es el 80).
Para usar el cuarto constructor habría que partir de un URL que ya tenga el protocolo, el servidor y quizás algún directorio y agregarse como cadena el resto de la dirección. Por ejemplo:
URL base=new URL("http","www.cnice.mecd.es","/enlaces");
new URL(base,"index.html");
El propósito principal de esta clase es facilitar la creación y uso de los URLs. El ejemplo GetURLInfo muestra cómo se puede usar la clase URL para obtener sus distintas partes. Ésta es la imagen de la consola tras una sesión de uso de GetURLInfo:
Se recomienda al lector jugar con este programa y usarlo para aclarar sus dudas sobre cómo se escriben los URLs y cuáles son sus partes.
Este es el código de GetURLInfo:
La clase URL permite abrir un InputStream para leer el recurso al que apunta pero normalmente antes de hacer eso deseamos saber algo más de ese recurso y para ello es mejor usar URLConnection que nos da más información y también nos permite abrir un InputStream.
El programa GetURLConnectionInfo intenta abrir una conexión al URL que se le ha pasado como parámetro usando c=url.openConnection(), y si lo consigue extrae infomación básica de la conexión como el tipo (MIME) de su contenido, el tamaño en bytes del archivo, la fecha de su última modificación, la fecha de expiración, y si viene en algún tipo de codificación. Toda esta información puede extraerse de la URLConnection c directamente. Si se quiere obtener el contenido del archivo hay que abrir el InputStream de la conexión mediante c.getInputStream() y luego leer la corriente de entrada. Lo que hace este programa en particular es leer las primeras 10 líneas del contenido del archivo si éste es de tipo text/html o text/plain. Hé aquí una imagen de la consola después de una llamada a este programa:
Se recomienda al alumno jugar con este programa tratando de abrir conexiones a distintos sitios de internet y a archivos de su propio ordenador y observar las diferentes respuestas y las excepciones que el programa puede escribir.
Como el alumno puede comprobar, URLConnection no permite abrir un OutputStream para enviar información a un recurso. Para hacer eso normalmente es necesario abrir un socket para establecer comunicación con algún programa en el servidor. La clase URL está diseñada sólo para obtener información.
Ahora presentamos una sencilla aplicación para descargar archivos de internet: el programa unidad09.descargaURL. Igual que a los otros dos programas de esta sección, se le pasa un URL como parámetro y lo que hace es intentar abrir una conexión a ese recurso y si lo consigue descargarlo, es decir, crear un archivo con su nombre y su contenido. Para organizar los archivos descargados el programa crea automáticamente un directorio llamado descargas, un subdirectorio con el nombre del servidor del recurso y los subdirectorios necesarios para crear una réplica de la trayectoria del URL y colocar ahí el archivo. Este sistema de organización de archivos es muy conveniente pues evita la duplicidad ya que crea una imagen virtual de toda la Web dentro del directorio descargas.
Éste es el código del programa:
El alumno debe usar el programa para descargar algunos archivos que le interesen y que haya localizado previamente con su navegador y comprobar que funciona tal como se describió arriba y luego estudiar el código localizando cómo lee el archivo y cómo crea los subdirectorios para colocarlo en su sitio.
Usando estas mismas herramientas y el sistema de organización de archivos usado en descargaURL se puede desarrollar un programa que descargue sitos web completos. Para ello habría que interpretar el contenido de las páginas web distinguiendo todas sus imágenes y los vínculos (conviene limitarse a los locales o a los del mismo servidor) y hacer que el programa los descargue. (Ejercicio 09.5)
¿Qué se puede hacer en internet desde un applet? Mucho y poco a la vez. Se puede hacer todo lo que se puede hacer en cualquier otro programa pero sólo con el servidor donde está el codebase del applet.
El ejemplo cuyo código aparece a continuación, unidad09.exploraInternet, es un sencillo navegador de internet y también del disco local. Es a la vez un applet y una aplicación. Cuando funciona como aplicación permite acceder a cualquier dirección local o de internet y leer los recursos que allí se encuentren. Cuando se usa una dirección local como punto de partida, funciona prácticamente igual que unidad08.exploraArchivos. Sin embargo también puede funcionar en una sitio de la Web, en el que se ponga el applet. La primera línea debe tener un URL válido y la segunda puede estar vacía o tener una trayectoria local basada en el URL de la primera línea. La lista enseñará los directorios y archivos que se encuentran en el URL resultante de las dos primeras líneas, esto si se opera sobre un disco local, pero si se opera con base en un URL absoluto, se obtienen los links de la página índice de ese URL. Este último resultado se debe a que actualmente los navegadores no dan información sobre la estructura de subdirectorios, sólo dan la información de los links existentes. En cuanto al funcionamiento cuando se hace un doble click sobre un elemento de la lista, estos se despliegan usando un marco de la clase miraTexto. similar al de la unidad anterior pero que usa un hilo para leer los archivos. Si se trata de imágenes, el programa las lee y las exhibe en un marco de la clase miraImagen. que no es sino una subclase sencilla de unidad08.miraImagen. Cuando el programa detecta que lo que está leyendo es un directorio o un html con links, pone en una lista todos los elementos del directorio o de todos los links. Cuando comienza el programa lee la raíz del disco local. El alumno debe usar un poco el programa escribiendo varios URL's en la primera línea, dando intro, y "navegando" con dobles clics sobre los elementos de la lista. Luego debe estudiar detenidamente el código, así como el de los constructores que usan un URL para las clases miraTexto y miraImagen.
Aquí se presenta exploraInternet como applet.
Este applet nos permite navegar por los subdirectorios del disco del ordenador local o por el servidor en donde se encuentra el codebase del applet de acuerdo con lo que éste devuelve como información en cada directorio. Si este applet se ejecuta localmente en un ordenador, permite navegar por los subdirectorios y cargar textos e imágenes, pero en un servidor de internet puede ser que sólo nos indique los vínculos de la página índice de cada subdirectorio. Cualquier intento de leer archivos o directorios en un servidor diferente del que contiene el codebase del applet dará una excepción de seguridad.
Para comprobar el funcionamiento del applet a través de un servidor web el alumno puede arrancar unidad09.HTTPServer y abrir esta página con el navegador usando el URL: http://localhost/unidad09.htm (o sustituyendo localhost por el nombre del ordenador).
La clase unida09.exploraInternet se define como un applet pero con un método main que permite utilizarla como aplicación, en cuyo caso del applet sólo se utilizan sus propiedades como Panel. Éste es el código:
Se trata de una clase que tiene varios detalles sutiles. El alumno debe estudiarla detalladamente. El método actualizar() lee las características del URL que se crea combinando el URL base que se obtiene del primer campo de texto, con el nombre del archivo que aparece en el segundo campo de texto o que se extrae de la lista. Allí se trata de distinguir entre imágenes, textos, html's y directorios aprovechando la información de getContent(). Los directorios a veces llegan en formato html y más frecuentemente en lugar de directorios el servidor Web devuelve sólo los links de la página índice. Las cosas se complican un poco más porque Netscape trata los URL's que corresponden a directorios de manera diferente a como lo hacen el appletviewer y el IExplorer. El método actualizarLista() intenta averiguar si de verdad tenemos un directorio y en tal caso busca todos los vínculos y los incorpora a la lista para poder usarlos como direcciones a las que podemos navegar. Para realizar este trabajo se usan objetos de la clase java.util.StringTokenizer.
Presentamos también el código de miraTexto y miraImagen para que el alumno los estudie y los compare con los de la unidad08.
Un applet no puede acceder a datos fuera del servidor donde se encuentra su código (su codebase), pero en cambio sí puede enviar al navegador la instrucción de abrir cualquier URL. Esto se hace con el método showDocument del AppletContext. Aprovechando esta propiedad presentamos un applet que "navega solo". Es un ejemplo sencillo pero que demuestra un camino más de aplicaciones para los applets. Si se pulsa el botón navegar solo aparecerá una ventana con el navegador exhibiendo cada 20 segundos una página diferente. Si selecciona un elemento de la lista mostrará sólo ese elemento y si escribe un URL en el campo de texto y pulsa intro, mostrará esa página.
Aquí está el código del applet:
El alumno debe observar que los URL que aparecen en la lista, el applet los lee de un archivo llamado vinculos.txt. Para realizar la lectura se crea un BufferedReader a partir del InputStream que url.openStream() devuelve. Entonces se leen cadenas con readLine() hasta que el BufferedReader devuelve una línea nula, lo cual señala que se ha terminado la lectura. Esto es un ejemplo más de cómo puede un applet leer recursos del servidor donde está su codebase.
Nota: Es importante saber que aunque las especificaciones de los applets en principio permiten que un applet lea recursos en todo el servidor donde se encuentra, en la práctica sólo permite leer en el directorio donde está el código del applet y en sus subdirectorios.
Igual que este ejemplo navega solo, se pueden programar applets que manden al navegador a páginas cuyas direcciones se deciden mediante una interacción más compleja, por ejemplo según el resultado de una prueba.