>> Lección 18 |
Internet y el paquete java.net
Java proporciona el paquete java.net para facilitar el trabajo de programación relacionado con internet. En esta lección estudiaremos primero las clases InetAddress, URL y URLConnection que son los instrumentos de programación de alto nivel y son suficientes para muchas aplicaciones. Las clases DatagramPacket, DatagramSocket, ServerSocket y Socket proporcionan herramientas para realizar conexiones de internet a bajo nivel. En este curso no estudiaremos lo correspondiente a Datagrams, pero sí el tema de los Sockets.
URL, URLConnection e InetAddress
Las siglas URL vienen de la frase en inglés Uniform Resource Locator que significa algo así como localizador uniforme de un recurso. Se trata de un instrumento para localizar cualquier recurso (archivo de texto, imagen, applet, etc...) en internet. Java proporciona una clase URL para representar estos localizadores. Tiene cuatro 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 dirección como se hace en un navegador. Por ejemplo:
new URL("http://www.cimat.mx/~jlabreu/CursoJava/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.cimat.mx","/~jlabreu/CursoJava/index.html");
Para usar el cuarto 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.cimat.mx","/~jlabreu");
new URL(base,"CursoJava/index.html");
Los navegadores de internet implementan el protocolo http y algunos más (file, ftp, gopher y posiblemente otros). Este es un ejemplo de una cadena con la que se puede construir un URL para un archivo local.
file:/C:/Mja/CursoJavaCimat/index.html
El ejemplo GetURLInfo muestra cómo se pueden utilizar las clases URL y URLConnection e InetAddress para crear un sencillo programa que desde la línea de comandos nos de información sobre el contenido de un URL específico. Primero crea el URL a partir de la cuerda que recibe desde la línea de comandos, luego extrae toda la información que se puede extraer de un URL sin hacer una conexión, a continuación obtiene el InetAddress y de él obtiene la dirección IP. Finalmente realiza la conexión y extrae información adicional como el tipo de contenido, la fecha de última actualización y el tamaño del archivo al que el URL apunta. Este es el código de GetURLInfo.
Se recomienda al lector usar el programa GetURLInfo desde la línea de comandos pasándole diversas direcciones absolutas y relativas.
El ejemplo cuyo código aparece a continuación, ejem09.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 ejem08.disco. Sin embargo también puede funcionar en cualquier dirección de la Web. 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 se despliegan usando un marco de la clase miraTexto. Si se trata de imágenes, el programa las lee y las exhibe en un marco de la clase 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.
Presentamos aquí otra vez el código de miraTexto y miraImagen para que el alumno pueda estudiar el funcionamiento de los constructores que usan un URL.
Estas clases se usan tanto en ejem08.disco como en ejem09.exploraInternet, en el primer caso se usan los constructores basados en nombres de archivos y en el segundo los basados en URL's.
El alumno observará que la lectura de las imágenes se hace con el método getImage(URL url) de Toolkit, al que hay que pasarle el URL ya creado y no simplemente la cadena que lo especifica. En el caso de miraTexto, para leer el archivo se crea un InputStream a partir del URL utilizando su método openStream(). También se utiliza una matriz de bytes como almacén temporal para recibir los bytes del InputStream y éstos se escriben a un ByteArrayOutputStream para que se encargue de dejarlos ordenados en otra matriz. Finalmente la matriz de bytes resultante se obtiene del ByteArrayOutputStream mediante toByteArray() y se transforma en una cadena que se pasa al cuadro de texto para su despliegue. Estos pasos podrían hacrse de otras maneras, pero ésta es una forma típica de hacerlo y el alumno debe estudiarla con cuidado para poder aplicarla en sus programas.
La construcción del applet-aplicación exploraInternet se basa en una sencilla clase llamada autoExitFrame:
Su función es simplemente crear una subclase de Frame que tenga incorporado el código para terminar la ejecución al pulsarse el botón de destrucción de la ventana. La clase exploraIntenet 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.
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.
A continuación presentamos la misma clase exploraInternet pero usada como un applet. Este applet nos permite navegar por los subdirectorios del disco de la computadora 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 una computadora, 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á un error y no funcionará.
Vínculos en applets
Aunque un applet no pueda acceder a datos fuera de su propio servidor, en cambio sí puede enviar al navegador la instrucción de cargar cualquier URL. Esto se hace con el método showDocument del AppletContext, como ya se explicó en la lección 6. 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 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 da 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. Este método de lectura de líneas es muy común y el alumno debe aprender a utilizarlo con facilidad.
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.
Sockets
Los sockets permiten comunicacarse directamente desde una computadora cliente a un servidor. Para abrir un socket basta dar el nombre del servidor y el número del puerto de comunicación que se va a usar. Del socket se pueden obtener corrientes de entrada y salida con getInputStream() y getOutputStream() y a través de ellas se puede realizar la comunicación. La idea es muy sencilla pero es necesario tener un servidor con quien comunicarse y conocer los protocolos de comunicación o tener acceso como programador a un servidor. Incluimos aquí un ejemplo de un applet que usa un socket para enviar un e-mail. Para que el ejemplo funcione es necesario que esté Ud. conectado a Internet pues el applet no se puede comunicar más que con el servidor en el que se encuentra su código. Así que en este caso el applet se ha colocado en http://www.cimat.mx/~jlabreu/CursoJava/ para que pueda funcionar. Envíese Ud. mismo un mensaje. Compruebe que el invento funciona verificando el correo y recibiendo su mensaje. ejem09.emailApplet no sólo es un applet, también es ejecutable.
Nota: En general los servidores smtp no aceptan e-mail de cualquiera, así que tendrán que buscar alguno que sí lo acepte..
El applet está basado en una clase llamada Mail que se encarga de crear el socket, abrir las corrientes de entrada y salida, enviar la información, esperar la respuesta y cerrar las corrientes y el socket. Estudie cada uno de estos pasos en el código de la clase Mail.
Los mensajes que se envían en las primeras líneas son parte del protocolo SMTP para servidores de correo.
Aquí está el código del applet:
El segundo ejemplo de trabajo con Sockets es un sencillo programa de comunicación entre varios clientes a través de un servidor. Arranque el servidor en su computadora con la llamada
java ejem09.myServer
Abra otra ventana del DOS y arranque una copia del cliente con:
java ejem09.myClient login1 SERVIDOR
donde SERVIDOR debe ser el nombre de red su computadora.
Abra una o dos ventanas más del DOS y realice en abra en ellas otras copias de ejem09.myClient usando diferente login pero el mismo SERVIDOR.
Desde cualquiera de las ventanas se puede escribir una línea y dar intro. Al hacerlo en todas las ventanas de clientes aparecerá la línea indicando su procedencia. Este sistema puede entonces funcionar como un sencillo "chat". Este pequeño sistema funciona perfectamente en red y en internet, basta instalar el servidor ejem09.myServer en un servidor de internet y ejem09.myClient en los diferentes clientes y hacer las llamadas a dichos programas correctamente.
Estudie el código de myServer.java y myClient.java buscando especialmente cómo se abre el ServerSocket en myServer y los Sockets en myClient 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. Observer que dentro de myServer.java existe otra clase llamada myConnection 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 y volver al DOS cuando en la ventana del servidor se da un intro o return. Observe cómo el servidor lleva control de todos los clientes activos para enviarles (método broadcast) los mensajes de cualquiera de ellos.
Por otro lado, myClient.java tiene también una clase llamada keyboardReader que se encarga de leer lo que el cliente escribe y enviarlo al servidor.
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.
José Luis Abreu y Marta Oliveró