UNIVERSIDAD NACIONAL DE SAN ANTONIO ABAD DEL CUSCO Departamento Académico de Informática REDES Y TELECOMUNICACIONES 2 Lab 04: Datagramas e Hilos (UDP) Ingº Manuel Peñaloza Figueroa “Dime y lo olvidaré. Muéstrame y lo recordaré. Involúcrame y lo entenderé” Proverbio chino 1. OBJETIVOS: 1.1 1.2 1.3 1.4 2. Entender lo básico de la comunicación por redes. Programar aplicaciones de red usando sockets. Aprender como construir aplicaciones cliente/servidor que se comunican usando sockets Aprender el uso de hilos y excepciones en Java. BASE TEORICA COMPLENTARIA Socket: Una interface creada por la aplicación del host local y controlada por el SO, en el cual el proceso aplicación puede tanto enviar como recibir mensajes a ó desde otro proceso aplicación. 3. RECURSOS Los recursos a utilizar en el trabajo de laboratorio son: 3.1 Java 4. DESARROLLO DE LA PRACTICA: En el presente trabajo de laboratorio se implementará en UDP el servicio CITAS, en el cual un servidor UDP enviará frases relevantes ó citas a los clientes que lo soliciten, haciendo uso del lenguaje Java. 4.1 Escribir una aplicación cliente/servidor que implemente en UDP el servicio “CITAS”, que pueda atender múltiples peticiones. 1 - Leunam UNIVERSIDAD NACIONAL DE SAN ANTONIO ABAD DEL CUSCO REDES Y TELECOMUNICACIONES 2 Lab 04: Datagramas e Hilos (UDP) APLICACIÓN SERVIDOR: ServerCitas.java /* * * */ import java.io.*; public class ServerCitas { // El metodo main simplemente crea un objeto ThreadServerCitas y lo arranca: public static void main(String[] args) throws IOException { new ThreadServerCitas().start(); } } ThreadServerCitas.java /* * * */ import java.io.*; import java.net.*; import java.util.*; public class ThreadServerCitas extends Thread { protected DatagramSocket socket = null; protected BufferedReader in = null; protected boolean masCitas = true; // constructor public ThreadServerCitas() throws IOException { this("ThreadServerCitas"); } // constructor public ThreadServerCitas(String nombre) throws IOException { super(nombre); // crear un socket DatagramSocket en el puerto 4445 (arbitrariamente elegido) // (Este es el DatagramSocket a través del cual el server se comunica con todos // sus clientes) socket = new DatagramSocket(4445); try { // abrir un BufferedReader sobre un archivo llamado una-linea.txt el cual // contiene una lista de citas. // Cada cita en el file esta sobre una linea por si misma. in = new BufferedReader(new FileReader("una-linea.txt")); 2 - Leunam UNIVERSIDAD NACIONAL DE SAN ANTONIO ABAD DEL CUSCO REDES Y TELECOMUNICACIONES 2 Lab 04: Datagramas e Hilos (UDP) } catch (FileNotFoundException e) { System.err.println("No se pudo abrir el archivo de citas. Servir la hora a cambio."); } } // método // El metodo run anula el run en la clase Thread y provee la implementacion p' el thread. public void run() { while (masCitas) { try { // Crear un arreglo de bytes byte[] buffer = new byte[256]; // Crear un DatagramPacket: // (el DatagramPacket será usado para recibir un datagrama desde el socket) // (el arreglo de byte contendra el mensaje desde el emisor al receptor) DatagramPacket paquete = new DatagramPacket(buffer, buffer.length); // Recibir datagrama desde el socket (la informacion recibida desde el // cliente se copia dentro del paquete). El metodo "receive" espera // por siempre hasta que un paquete es recibido. Si ningun paquete es // recibido, el server no hace progreso adicional y solamente espera. // (el arribo del paquete mismo indica una petición desde un cliente) socket.receive(paquete); // construir la respuesta String cita = null; if (in == null) // si el archivo de citas no se abrió por alguna razón cita = new Date().toString(); else cita = getSiguienteCita(); // convertir el String a un arreglo de Bytes buffer = cita.getBytes(); // Enviar la respuesta al cliente en tal "direccion" y en tal "puerto" // Obtener la dirección IP y el # de puerto a partir del DatagramPacket // recibido desde el cliente. InetAddress direccionIP = paquete.getAddress(); int puerto = paquete.getPort(); paquete = new DatagramPacket(buffer, buffer.length, direccionIP, puerto); socket.send(paquete); } catch (IOException e) { e.printStackTrace(); masCitas = false; } } socket.close(); 3 - Leunam UNIVERSIDAD NACIONAL DE SAN ANTONIO ABAD DEL CUSCO REDES Y TELECOMUNICACIONES 2 Lab 04: Datagramas e Hilos (UDP) } // método protected String getSiguienteCita() { String valorDeRetorno = null; try { // leer del archivo y cargar la variable if ((valorDeRetorno = in.readLine()) == null) { in.close(); masCitas = false; valorDeRetorno = "No mas citas. Adios."; } } catch (IOException e) { valorDeRetorno = "IOException occurrio en el servidor."; } return valorDeRetorno; } } 4.2 Escribir un archivo de texto que contenga por lo menos 100 citas de 1 línea, tal como se muestra a continuación: una-linea.txt Siempre recuerda Tú eres único, justamente como cualquier otro. Mejor entender un poco que no entender mucho. C:\ es la raíz de todos los directorios. Buena programación es 99% sudor y 1% café. … … … 4.3 Escribir una aplicación cliente en UDP que haga uso del servicio “CITAS”. APLICACIÓN CLIENTE: ClienteCitas.java /* * * */ import java.io.*; import java.net.*; import java.util.*; public class ClienteCitas { public static void main(String[] args) throws IOException { 4 - Leunam UNIVERSIDAD NACIONAL DE SAN ANTONIO ABAD DEL CUSCO REDES Y TELECOMUNICACIONES 2 Lab 04: Datagramas e Hilos (UDP) if (args.length != 1) { System.out.println("Uso: java ClienteCitas <nombre_host>"); return; } // crear el DatagramSocket del cliente // (el constructor justamente liga el DatagramSocket a cualquier puerto local // disponible. No importa a q' puerto el cliente es ligado pues los // DatagramPackets contienen la información de direccionamiento). DatagramSocket socket = new DatagramSocket(); // enviar peticion al server byte[] buffer = new byte[256]; // obtener la direccion IP para el host nombrado en la línea de comandos, q' es // el nombre de la máquina en la cual el server está corriendo // (el numero de puerto 4445 es el numero de puerto que el server uso para crear // su DatagramSocket) InetAddress direccionIP = InetAddress.getByName(args[0]); DatagramPacket paquete = new DatagramPacket(buffer, buffer.length, direccionIP, 4445); socket.send(paquete); // obtener respuesta paquete = new DatagramPacket(buffer, buffer.length); socket.receive(paquete); // mostrar la respuesta ó cita String citaRecibida = new String(paquete.getData(), 0, paquete.getLength()); System.out.println("Cita del momento: " + citaRecibida); socket.close(); } } 4.4 En Windows abrir 3 ó más ventanas DOS, en una de ellas compilar el (ó los) correspondiente(s) archivo(s) en Java del servidor y correr la aplicación servidor, y en el resto de ventanas compilar el correspondiente archivo en Java del cliente y correr la aplicación cliente. 5. CONTROL: TRABAJOS DE LABORATORIO. 5.1 La asistencia al laboratorio se considera como tal si se cumple con lo solicitado en 4.4. 5 - Leunam