Vous êtes sur la page 1sur 12

Universidad del Bo-Bo Facultad de Ciencias Empresariales Ingeniera Civil en Informtica Sede Chilln

Comunicacin de Datos y Redes

Tarea Aplicacin Cliente Servidor


Integrantes
Javier Andana Quijada Sebastin Mora Espinoza

Asignatura
Comunicacin de Datos y Redes

Fecha

28-04-2013

Introduccin
En el presente informe se mostraran los diferentes aspectos relacionados con el desarrollo del juego el ahorcado utilizando la arquitectura de cliente servidor, mediante las clases Socket y ServerSocketde la API de Java. Los aspectos que se explicaran sern, la definicin de la unidad de datos diseada para la transmisin de informacin cliente - servidor y el tipo de servicio de transporte utilizado.

Especificaciones del juego el ahorcado


Para la realizacin del juego del ahorcado se utilizo una arquitectura de cliente - servidor creando dos clases de java diferentes la ServidorTCP que representara el servidor y la ClienteTCP que representa el cliente.

Funcionamiento del juego


El servidor contiene la lgica del juego. Lo que hace al iniciar una partida es escoger completamente al azar una palabra a adivinar desde un arreglo de String, que contiene diferentes trminos. Adems se encargar de evaluar cada letra que enve el cliente, llevando un conteo de los intentos que tiene disponible el jugador. Los intentos disminuyen cada vez que el usuario enva una letra y no acierte a ninguna letra de la palabra seleccionada inicialmente. Por otro lado actualizar el String que representa los caracteres adivinados de la palabra actual. Luego de realizar el procesamiento del mensaje desde el cliente y subsiguiente actualizacin de su estado y sus variables, el servidor le responder al cliente enviando un mensaje con las variables que se manejan actualmente en ste. Por otra parte el cliente solo leer desde teclado las diferentes letras que ingrese el usuario y las enviara mediante un mensaje al servidor, luego recibir una respuesta por parte de ste y mostrara el resultado de la accin por pantalla actualizando el String que representa los caracteres adivinados, el cual obtuvo desde el servidor y la cantidad de intentos disponibles que tiene el jugador.

Unidad de datos para la comunicacin y variables del juego


Como se explic anteriormente es necesario establecer un mecanismo de mensajes entre el cliente y el servidor de manera de lograr que, entre ellos, compartan todos los datos que sean necesarios para el funcionamiento del juego. Para esto es que se defini una unidad de datos que permita el flujo de esta informaron. La estructura de datos para la comunicacin es un String que contiene las diferentes variables que hacen posible el funcionamiento del juego y el intercambio de datos. El String est formado por las variables separadas mediante un carcter #, lo que indica el termino de un campo y el inicio del siguiente. Los diferentes componentes del mensaje se especificana continuacin: intestadoJuego: Este campo es un int que puede ser asignado con 5 valores distintos. 0 indica INACTIVO; 1 indica JUGANDO; 2 indica GANO; 3 indica PERDIO; 4 indica SOLICITANDO_JUEGO_NUEVO; 5 indica JUEGO_TERMINADO;

int intentosRestantes: Este campo especifica el nmero de intentos que tiene disponible el usuario.Se inicializa siempre en seis intentos. char letra: Indicara la letra ingresada desde teclado por el jugador la cual ser enviada por el cliente al servidor para que este evale si pertenece a la palabra que el jugador est tratando de adivinar. String palabraEnProgreso: Representa el String que indica las letras de la palabra en un momento dado han sido adivinadas y las letras que no lo han sido mediante el carcter de guion bajo. int nroMensaje: nos indicar el nmero de mensajes que se han enviado desde el servidor al cliente.

De esta manera todos los campos anteriormente descritos se concatenan utilizando como separador el carcter # para formar un String de la siguiente manera:
estadoJuego+"#"+intentosRestantes+"#"+letra+"#"+palabraEnProgreso+"#"+nroMensaje

Por otra parte en el Servidor se maneja una variable llamada palabra la cual es la que representa la palabra en juego. palabra: Indicala palabra que el jugador debe tratar de adivinar. este atributo solo se encuentra en la clase ServidorTCP.

Tipo de servicio de transporte


Una vez definida la unidad de datos es necesario escoger un tipo de servicio de transporte utilizado para el envo de estos mensajes. Para esto tenemos dos alternativas, un tipo de servicio confiable el cual nos garantiza que la informacin llegue completamente correcta o un servicio no confiable el cual no nos asegura que los datos lleguen totalmente correctos, pero si nos brinda una mayor velocidad de traspaso de informacin. Para el juego de ahorcado se determino utilizar un servicio confiable en desmedro de uno no confiable debido a que es ms importante la integridad de la informacin que la velocidad a la que viaja ya que si la informacin sufre cambios mientras es transmitida podra desencadenar en un incorrecto funcionamiento del juego lo que nos deja expuesto a eventuales errores dentro de la lgica y por ende generar una aplicacin inestable y poco segura. Este servicio confiable se ve reflejado en el programa al momento de utilizar el socket de tipo SocketStream (en java representado por la clase Socket) el cual utiliza un servicio orientado a la conexin, donde los datos se transfieren sin encuadrarlos en registros o bloques, asegurndose de esta manera que los datos lleguen al destino en el orden detransmisin. Si se rompe la conexin entre los procesos, stos sern informados de tal suceso para que tomen las medidas oportunas, por eso se dice que estn libres de errores. El protocolo de comunicaciones con Stream es un protocolo orientado a conexin, ya que para establecer una comunicacin utilizando el protocolo TCP (Transmission Control Protocol), hay que establecer en primer lugar una conexin entre un par de sockets. Mientras uno de los sockets atiende peticiones de conexin (servidor), el otro solicita una conexin (cliente). Una vez que los dos sockets estn conectados, se pueden utilizar para transmitir datos en ambas direcciones.

Esquema de los estados, mensajes y jugadores


Las distintas clases que interactan poseen estados internos. El mensaje que se enva tambin lleva un estado. Los estados internos de las clases se traspasan a su destinatario mediante el mensaje. Las distintas clases toman decisiones evaluando el mensaje de manera que agregan o modifican ste, as como tambin modificando sus estados internos. En un principio ServidorTCP est a la espera (estado INACTIVO) de algn cliente que desee jugar. Un jugador 1 inicia la clase ClienteTCP, que tambin est en estado INACTIVO. El jugador 1 desea jugar y se conecta al servidor. ServidorTCP acepta la conexin del cliente y queda a la espera de algn mensaje de ste. Supongamos que existe un jugador 2 que intenta conectarse con ServidorTCP. Como ServidorTCP ya est aceptando las peticiones de un cliente, el jugador 2 queda en espera. ClienteTCP enva una peticin de juego (SOLICITANDO_NUEVO_JUEGO) al cliente a travs del mensaje y ServidorTCP la recibe cambiando su estado a JUGANDO. Luego ServidorTCP enva un mensaje de respuesta al cliente con el String de mensaje y este conteniendo el estado JUGANDO. ClienteTCP lee el mensaje y despliega por pantalla al jugador 1 el juego aprovechando los datos obtenidos desde el mensaje, adems cambiando su estado interno. ClienteTCP responde enviando en el mensaje la letra ingresada por el jugador 1 y el estado JUGANDO y ServidorTCP recibe el mensaje. ServidorTCP y ClienteTCP se traspasan informacin hasta que el jugador gane o pierda segn las letras que enve al servidor, y cuando ocurre esto ClienteTCP terminara la ejecucin de su programa indicndole al jugador1 que el juego ha sido ganado o perdido, cambiando su estado a JUEGO_TERMINADO, y entrando en accin del jugador 2 de la misma forma que lo hizo el jugador 1. ServidorTCP repite el juego con los clientes hasta que se decida terminar el servicio que entrega el servidor.

ClienteTCP.java
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.util.StringTokenizer; /* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * * @author Sebastian */ public class ClienteTCP { //DECLARACIONES private static final int INACTIVO = 0; private static final int JUGANDO = 1; private static final int GANO = 2; private static final int PERDIO = 3; private static final int SOLICITANDO_JUEGO_NUEVO = 4; private static final int JUEGO_TERMINADO = 5; //ATRIBUTOS DE LA CONEXION private static final int puerto = 6112; private static BufferedReader in = null; private static DataOutputStream out = null; private static Socket conexion; //ATRIBUTOS DEL JUEGO private static int estadoJuego = INACTIVO; private static int intentosRestantes = 6; private static char letra = '*'; private static String palabraEnProgreso = "*"; private static Integer nroMensaje = 0; public static void main(String[] args) { try { conexion = new Socket("186.78.24.232", 10733); BufferedReader entradaUsuario = new BufferedReader(new InputStreamReader(System.in)); System.out.println("iniciando Conexion con el servidor..."); in = new BufferedReader(new InputStreamReader(conexion.getInputStream())); out = new DataOutputStream(conexion.getOutputStream()); System.out.println("conexion realizada..."); boolean jugando = true; while (jugando == true) { if (estadoJuego == INACTIVO) { setEstadoJuego(SOLICITANDO_JUEGO_NUEVO); enviarMensaje(); imprimirSalida(); } else { //LEER MENSAJE DESDE SERVIDOR leerMensaje(in.readLine()); imprimirEntrada(); if (estadoJuego == JUGANDO) { //IMPRIMIR MENSAJE EN PANTALLA Y LEER UNA LETRA DEL CLIENTE imprimirMensajeEnPantalla(); System.out.println("ingrese una letra: "); //SETEAR LA LETRA LEIDA POR EL CLIENTE setLetra(entradaUsuario.readLine().charAt(0)); enviarMensaje(); } else { if (estadoJuego == GANO) { setEstadoJuego(JUEGO_TERMINADO);

//

//

imprimirMensajeEnPantalla(); jugando = false; System.out.println("FELICITACIONES HAS GANADO EL JUEGO EL AHORCADO"); } if (estadoJuego == PERDIO) { setEstadoJuego(JUEGO_TERMINADO); imprimirMensajeEnPantalla(); jugando = false; System.out.println("QUE LASTIMA , NO TE QUEDAN MAS INTENTOS.\nHAS PERDIDO EL JUEGO EL AHORCADO"); } System.out.println("programa terminado..."); } } } } catch (IOException ex) { System.out.println("ERROR DE ENRADA/SALIDA"); System.out.println("No fue posible realizar la conexion, posiblemente el servidor este inactivo."); } } private static void enviarMensaje() { try { if (estadoJuego == SOLICITANDO_JUEGO_NUEVO) { out.writeBytes(crearMensajeRespuesta()); } else { out.writeBytes(crearMensajeRespuesta()); } } catch (IOException iOException) { System.out.println("ERROR AL ENVIAR EL MENSAJE"); } } public static String crearMensajeRespuesta() { return estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje + "\n"; } public static int getEstadoJuego() { return estadoJuego; } public static char getLetra() { return letra; } public static int getNroIntentos() { return intentosRestantes; } public static String getPalabraEnProgreso() { return palabraEnProgreso; } public static void setEstadoJuego(int estadoJuego) { ClienteTCP.estadoJuego = estadoJuego; } public static void setLetra(char letra) { ClienteTCP.letra = letra; } public static void leerMensaje(String mensaje) { StringTokenizer stk = new StringTokenizer(mensaje, "#"); while (stk.hasMoreTokens()) { estadoJuego = Integer.valueOf(stk.nextToken()); intentosRestantes = Integer.valueOf(stk.nextToken());

letra = stk.nextToken().charAt(0); palabraEnProgreso = stk.nextToken(); nroMensaje = Integer.valueOf(stk.nextToken()); } } private static void imprimirMensajeEnPantalla() { //IMPRIMIENDO MENSAJE EN PANTALLA System.out.println("########### JUEGO EL AHORCADO ###########"); imprimirAhorcado(intentosRestantes); System.out.println("\nPALABRA ACTUAL: " + getPalabraActualGuionBajo()); System.out.println("INTENTOS RESTANTES: " + intentosRestantes); } private static String getPalabraActualGuionBajo() { String[] a = palabraEnProgreso.split(""); String impr = ""; for (int i = 0; i < a.length; i++) { impr += a[i] + " "; } return impr; } private static String mostrarEstado() { if (estadoJuego == 0) { return "INACTIVO"; } else { if (estadoJuego == 1) { return "JUGANDO"; } else { if (estadoJuego == 2) { return "GANO"; } else { if (estadoJuego == 3) { return "PERDIO"; } else { if (estadoJuego == 4) { return "SOLICITANDO_JUEGO_NUEVO"; } else { return "JUEGO_TERMINADO"; } } } } } } private static void imprimirEntrada() { String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje; System.out.println("LEIDO POR CLIENTE: " + a + "\n" + mostrarEstado()); } private static void imprimirSalida() { String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje; System.out.println("ENVIADO POR CLIENTE: " + a + "\n" + mostrarEstado()); } private static void imprimirAhorcado(int intentosRestantes) { System.out.println(" -----------\n | if (intentosRestantes < 1) { System.out.println(" |\n } else { if (intentosRestantes < 2) { System.out.println(" o |\n } else { |"); |\n |\n |"); |");

if (intentosRestantes < 3) { System.out.println(" |");

o_

|\n

|\n

} else { if (intentosRestantes < 4) { System.out.println(" |");

_o_

|\n

l|

|\n

} else { if (intentosRestantes < 5) { System.out.println(" |");

_o_

|\n

l|l

|\n

} else { if (intentosRestantes < 6) { System.out.println(" ) |");

_o_

|\n

l|l

|\n

} else { if (intentosRestantes < 7) { System.out.println(" ( ) |"); } } } } } } } System.out.print(" + "______l_____\n"); } } |\n

_o_

|\n

l|l

|\n

|\n____________"

ServidorTCP.java
import import import import import import import import import java.io.BufferedReader; java.io.DataOutputStream; java.io.IOException; java.io.InputStreamReader; java.net.ServerSocket; java.net.Socket; java.util.StringTokenizer; java.util.logging.Level; java.util.logging.Logger;

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * * @author Sebastian */ public class ServidorTCP { //DECLARACIONES private static final int INACTIVO = 0; private static final int JUGANDO = 1; private static final int GANO = 2; private static final int PERDIO = 3; private static final int SOLICITANDO_JUEGO_NUEVO = 4; //ATRIBUTOS DEL SERVIDOR private static final int nroPuerto = 6112; private static boolean SocketDisponible = true; private static int conexionesRealizadas = 0; private static Socket con; //ATRIBUTOS DEL JUEGO private static int estadoJuego = INACTIVO; private static char letra = '?';

private static String palabra = "?"; private static String palabraEnProgreso = "?"; private static int nroIntentos = 6; //PALABRAS EN EL SERVIDOR static private final String[] palabrasAhorcado = {"reingenieria", "cubeta", "tunelizacion", "protocolo", "puertos", "conexion", "broadcasting", "direccion", "internet", "router", "switch", "wifi", "estandar", "socket", "transporte", "enlace", "capas", "arquitectura", "cliente", "servidor", "proxy", "firewall", "redes", "LAN", "WAN", "MAN", "hub", "concentrador", "datagrama", "puente", "fibra", "TCP", "UDP", "mascara", "gateway", "servidor", "DNS", "cliente", "conmutacion", "circuito", "satelite", "coaxial", "microondas", "seal", "ingrarrojos", "token", "anillo", "bus", "control", "flujo", "congestion", "enrutamiento", "aplicacion", "correo", "peertopeer", "reingenieria", "cubeta", "tunelizacion", "protocolo", "puertos", "conexion", "broadcasting", "direccion", "internet", "router", "switch", "wifi", "estandar", "socket", "transporte", "enlace", "capas", "arquitectura", "cliente", "servidor", "proxy", "firewall", "redes", "LAN", "WAN", "MAN", "hub", "concentrador", "datagrama", "puente", "fibra", "TCP", "UDP", "mascara", "gateway", "servidor", "DNS", "cliente", "conmutacion", "circuito", "satelite", "coaxial", "microondas", "seal", "ingrarrojos", "token", "anillo", "bus", "control", "flujo", "congestion", "enrutamiento", "aplicacion", "correo", "peertopeer"}; private static int nroMensaje = 0; public static void main(String[] args) throws IOException { ServerSocket socketDeServicio = null; try { socketDeServicio = new ServerSocket(nroPuerto); BufferedReader entrada; DataOutputStream salida; while (true) { try { if (SocketDisponible) { //EL SOCKET ESTA DISPONIBLE, POR LO TANTO ACA NO SE ESTA EN JUEGO if (estadoJuego == INACTIVO) { System.out.println("\nesperando cliente..."); con = socketDeServicio.accept(); System.out.println("conexion aceptada...\n"); salida = new DataOutputStream(con.getOutputStream()); entrada = new BufferedReader(new InputStreamReader(con.getInputStream())); conexionesRealizadas++; System.out.println("SERVIDOR : conexion aceptada a cliente " + conexionesRealizadas); /*leer primer mensaje, peticion de inicio de juego desde el *cliente.*/ leerMensaje(entrada.readLine()); // imprimirEntrada(); procesarMensaje(); salida.writeBytes(responderMensaje()); // imprimirSalida(); } } else { entrada = new BufferedReader(new InputStreamReader(con.getInputStream())); salida = new DataOutputStream(con.getOutputStream()); //EL SOCKET ESTA OCUPADO, POR LO TANTO ACA SE ESTA EN JUEGO if (estadoJuego == JUGANDO) { leerMensaje(entrada.readLine()); // imprimirEntrada(); procesarMensaje(); salida.writeBytes(responderMensaje()); // imprimirSalida(); if (estadoJuego == GANO || estadoJuego == PERDIO) { estadoJuego = INACTIVO; SocketDisponible = true; System.out.println("JUEGO NRO " + conexionesRealizadas + " TERMINADO...");

} } } } catch (java.net.SocketException e) { System.out.println("TERMINO ABRUPTO DE LA CONEXION CON EL CLIENTE."); estadoJuego = INACTIVO; SocketDisponible = true; System.out.println("JUEGO NRO " + conexionesRealizadas + " TERMINADO..."); } } } catch (IOException BindException) { System.out.println("La maquina virtual de java ya esta ocupando el socket" + "en ese puerto, intente iniciar el servicio con otro puerto"); } } private static void leerMensaje(String mensaje) { StringTokenizer stk = new StringTokenizer(mensaje, "#"); while (stk.hasMoreTokens()) { estadoJuego = Integer.valueOf(stk.nextToken()); nroIntentos = Integer.valueOf(stk.nextToken()); letra = stk.nextToken().toUpperCase().charAt(0); palabraEnProgreso = stk.nextToken().toUpperCase(); nroMensaje = Integer.valueOf(stk.nextToken()); } nroMensaje++; } private static void procesarMensaje() { if (estadoJuego == SOLICITANDO_JUEGO_NUEVO) { setSocketDisponible(false); setEstadoJuego(JUGANDO); setNroIntentos(6); setLetra('?'); setPalabra(escojerPalabraJuegoNuevo()); setPalabraEnProgreso(); } else { if (estadoJuego == JUGANDO) { if (huboAcierto()) { reemplazarLetra(); if (ganoJuego()) { estadoJuego = GANO; System.out.println("SERVIDOR : CLIENTE HA GANADO JUEGO"); } else { System.out.println("SERVIDOR : CLIENTE HA ACERTADO PALABRA"); } } else { nroIntentos--; System.out.println("SERVIDOR : SE LE HA DISMINUIDO UN INTENTO AL CLIENTE POR NO HABER ACERTADO"); if (nroIntentos == 0) { estadoJuego = PERDIO; System.out.println("SERVIDOR : CLIENTE HA PERDIDO JUEGO"); } } } else { try { System.out.println("SERVIDOR : cerrando conexion..."); con.shutdownOutput(); SocketDisponible = true; System.out.println("SERVIDOR : conexion finalizada."); } catch (IOException ex) { Logger.getLogger(ServidorTCP.class.getName()).log(Level.SEVERE, null, ex); } } }

} private static String responderMensaje() { String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje + "\n"; return a; } public static void setSocketDisponible(boolean SocketDisponible) { ServidorTCP.SocketDisponible = SocketDisponible; } public static void setConexionesRealizadas(int conexionesRealizadas) { ServidorTCP.conexionesRealizadas = conexionesRealizadas; } public static void setEstadoJuego(int estadoJuego) { ServidorTCP.estadoJuego = estadoJuego; } public static void setLetra(char letra) { ServidorTCP.letra = letra; } public static void setNroIntentos(int nroIntentos) { ServidorTCP.nroIntentos = nroIntentos; } public static void setPalabra(String palabra) { ServidorTCP.palabra = palabra; } public static void setPalabraEnProgreso(String palabraEnProgreso) { ServidorTCP.palabraEnProgreso = palabraEnProgreso; } private static String escojerPalabraJuegoNuevo() { return palabrasAhorcado[(int) (Math.random() * palabrasAhorcado.length)]; } private static void setPalabraEnProgreso() { String p = ""; for (int i = 0; i < palabra.length(); i++) { p += "_"; } palabraEnProgreso = p; } private static boolean huboAcierto() { boolean tuvoAcierto = true; //PRIMERO DEBEMOS COMPROBAR QUE LA LETRA NO SE PREPITA CON LO QUE //YA TENEMOS COMPLETADO ACTUALMENTE tuvoAcierto = !seRepite(letra, palabraEnProgreso) && esParteDeLaPalabra(letra, palabra); return tuvoAcierto; } private static boolean seRepite(char l, String enProgreso) { boolean repite = false; char[] prog = enProgreso.toCharArray(); for (int i = 0; i < prog.length; i++) { if (l == prog[i]) { repite = true; } } return repite; } private static boolean esParteDeLaPalabra(char letra, String palabra) {

boolean esParte = false; char[] pa = palabra.toUpperCase().toCharArray(); for (int i = 0; i < pa.length; i++) { if (letra == pa[i]) { esParte = true; } } return esParte; } private static void reemplazarLetra() { String[] enProg = palabraEnProgreso.split(""); String[] pal = palabra.split(""); String reemplazada = ""; for (int i = 0; i < pal.length; i++) { if (String.valueOf(letra).equalsIgnoreCase(pal[i])) { enProg[i] = String.valueOf(letra); } reemplazada += enProg[i]; } palabraEnProgreso = reemplazada; } private static boolean ganoJuego() { if (palabraEnProgreso.equalsIgnoreCase(palabra)) { return true; } else { return false; } } private static String mostrarEstado() { if (estadoJuego == 0) { return "INACTIVO"; } else { if (estadoJuego == 1) { return "JUGANDO"; } else { if (estadoJuego == 2) { return "GANO"; } else { if (estadoJuego == 3) { return "PERDIO"; } else { if (estadoJuego == 4) { return "SOLICITANDO_JUEGO_NUEVO"; } else { return "JUEGO_TERMINADO"; } } } } } } private static void imprimirEntrada() { String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje; System.out.println("\nLEIDO POR SERVIDOR: " + a + "\n" + mostrarEstado()); } private static void imprimirSalida() { String a = estadoJuego + "#" + nroIntentos + "#" + letra + "#" + palabraEnProgreso + "#" + nroMensaje; System.out.println("\nENVIADO POR SERVIDOR: " + a + "\n" + mostrarEstado()); } }

Vous aimerez peut-être aussi