domingo, 23 de febrero de 2014

Reingeniería de Software

Introducción


El proceso de evolución de los sistemas implica comprender el programa que tiene que cambiarse, y a continuación implementar estos cambios. Sin embargo, muchos sistemas, especialmente los sistemas heredados más antiguos son difíciles de comprender y de cambiar. Los programas pueden haber sido optimizados originalmente para su rendimiento o utilización de la memoria a expensas de su comprensibilidad o, a lo largo del tiempo, la estructura inicial del programa puede haberse corrompido por una serie de cambios.

Reingeniería de Software


Para  simplificar los problemas de cambiar sus sistemas heredados, una compañía puede decidir hacer reingeniería sobre estos sistemas para mejorar su estructura y comprensibilidad. La reingeniería de software se refiere a la reimplementación de los sistemas heredados para hacerlos más mantenibles. La reingeniería puede implicar redocumentar el sistema, organizar y reestructurar el sistema, traducir el sistema a un lenguaje de programación más moderno, y modificar y actualizar su estructura y vales de los datos del sistema. La funcionalidad del software no se cambia y, normalmente, a arquitectura del sistema también sigue siendo la misma. (Sommerville, 2005)

El proceso de reingeniería es muy elaborado y trae problemas como un alto grado de riesgo puesto que se pueden producir errores en la especificación, o puede haber errores en el desarrollo. Además en cuanto a costes este proceso de la ingeniería de software es significativamente el más caro, sin embargo, sigue siendo relativamente menor que el coste de desarrollar un nuevo software.
En la reingeniería de software se pueden distinguir las siguientes seis etapas, que pueden seguir o no una secuencia lineal, pero siempre se desarrollarán cíclicamente: (Pressman, 2002)


  • Análisis de inventarios.
  • Reestructuración de documentos.
  • Ingeniería inversa.
  • Reestructuración del código.
  • Reestructuración de los datos.
  • Ingeniería avanzada.








Análisis de inventarios:

Se analizan los inventarios que poseen las empresas o el usuario sobre las características de la aplicación. En ocasiones son simples hojas de cálculo con descripciones detalladas (tamaño, edad, importancia para el negocio) de las aplicaciones activas. Así se sabrá a que recursos se aplicará la reingeniería.


Reestructuración de documentos:

Normalmente en los sistemas heredados, la documentación es muy débil; por lo que es necesario evaluar que documentación debe actualizarse. En ocasiones se debe volver a documentarse por completo pero lo adecuado es recortar la creación de documentos al mínimo ya que ocupa muchos recursos y tiempo.


Ingeniería inversa:

Durante esta etapa se plantea la posibilidad de recuperar el diseño de la aplicación. Con diversas herramientas y conocimientos se extrae del programa existente información de la arquitectura y de los procesos así como información de los datos.


Reestructuración de código:

Se analiza el código fuente y se indican las violaciones de las estructuras de programación estructurada como lo son los estándares, entonces se reestructura el código.


Reestructuración de los datos:

Se definen los modelos de datos necesarios, se identifican los objetivos y los atributos, y después se revisa la calidad de las estructuras existentes. Cuando son débiles, se debe aplicar una reingeniería a los datos.


Ingeniería avanzada:

La ingeniería directa no solo recupera la información de diseño a partir del software existente, también utiliza esta información para alterar o reconstruir el sistema existente con la finalidad de mejorar su calidad global. En la mayoría de los casos el software sometido a reingeniería vuelve a implementar la función del sistema existente y también añade nuevas funciones o mejoras.

Conclusión

Las empresas al utilizar software durante varios años, es inevitable que se deban realizar cambios y mejoras o hasta crear un nuevo sistema totalmente innovado. Son ellas que dependiendo de un análisis decidirán que opción se adapta mejor a sus necesidades y es que es sin duda alguna que aplicar algo de mantenimiento siempre será menos costoso que adquirir una aplicación nueva.
En reingeniería sus costos son elevados, debido a que deben realizarlos profesionales muy bien capacitados y con una gran habilidad de extracción de datos y muy buena lógica, sin embargo, sigue siendo una opción muy recomendable para sacar adelante el proceso de negocios de una empresa.


Trabajos citados

Pressman, R. S. (2002). Ingeniería de Software: Un enfoque práctico. Madrid: McGRAW-HILL.
Sommerville, I. (2005). Ingeniería del Software. Madrid: Pearson Eduacion.

Descargar formato PDF



domingo, 16 de febrero de 2014

Leyes de Lehman

Introducción

Durante la evolución del software, podremos apreciar que se van presentando diversas problemáticas principalmente cuando se le hacen mejoras o reparaciones al sistema tanto internos (como cambios al código o al diseño, etc.), como externos (cambio de equipo de trabajo, en el proceso de negocios, etc.). Por esta razón debemos estar conscientes del proceso de evolución y nos apoyaremos estudiando las Leyes de Lehman.

Leyes de Lehman

La dinámica de evolución de los programas es el estudio de los cambios del sistema. La mayor parte del trabajo en esta área ha sido realizada por Lehman y Belady. A partir de estos estudios, propusieron un conjunto se leyes empíricas (Las leyes de Lehman) concernientes a los cambios y crecimiento de los sistemas tango grandes como chicos. Las cinco primeras leyes fueron las propuestas iniciales de Lehman; las leyes restantes fueron añadidas después de posteriores trabajos, dando como resultado lo siguiente:

  • Cambio continuado.

Un programa que se usa en un entorno real necesariamente debe cambiar o se volverá progresivamente menos útil en ese entorno.

  • Complejidad creciente.

A medida que un programa en evolución cambia, su estructura tiende a ser cada vez más compleja. Se deben dedicar recurso extras para preservar y simplificar la estructura.

  • Evolución prolongada del programa.

La evolución de los programas es un proceso autorregulativo. Los tributos de los sistemas, tales como tamaño, tiempo entre entregas y el número de errores documentados, son aproximadamente invariables para cada entrega del sistema.

Esto a su vez implica un aumento progresivo del esfuerzo de mantenimiento, a menos que se realice algún tipo de mantenimiento perfectivo a este respecto.

  • Estabilidad organizacional.

Es importante la buena comunicación entre cada integrante del equipo de desarrollo para lograr una eficiencia mutua que se verá reflejada a lo largo de la evolución del sistema.

  • Conservación de la familiaridad.

A medida que se realicen cambios, todos aquellos que estén asociados al sistema, deberán conocer dichos cambios y su impacto en el comportamiento y funcionalidad del mismo, para así seguirlo desarrollando eficientemente, por lo que es preferible realizar pequeños cambios a uno grande, sabiendo que dichos cambios traerán consigo, indudablemente, nuevos defectos.

  • Crecimiento continuado.

La funcionalidad ofrecida por los sistemas tiene que crecer continuamente para mantener la satisfacción de los usuarios. 

  • Decremento de la calidad.

La calidad de los sistemas comenzará a disminuir a menos que dichos sistemas se adapten a los cambios en su entorno de funcionamiento. 

  • Realimentación del sistema.

El proceso de evolución del sistema y los cambios desarrollados toman como base la realimentación por parte de los usuarios realizada en diferentes niveles y de forma iterativa, para así satisfacer las necesidades que se presentan constantemente.

Conclusión

Lehman dio un magnifico aporte a la Ingeniería de Software, puesto que sus leyes nos permiten controlar cambios y fallas inesperados en el software. Si las consideramos podremos crear un sistema con mayor calidad que efectivamente nos ayudará a tener un mejor producto para nuestro cliente, evaluando futuros problemas que se presenten al momento de dar mantenimiento o soporte.

Bibliografía

M.M, L. (1996). Laws of Software Evolution Revisited. London: Springer Verlag.
Sicilia, M. A. (24 de Noviembre de 2008). Leyes de la Evolución del Software. Recuperado el Febrero de 2013, de Connexions: http://cnx.org/content/m17406/latest/
Sommerville, I. (2005). Ingeniería del Software. Madrid: Pearson Eduacion.


 Descarga formato PDF

domingo, 2 de febrero de 2014

Mantenimiento de Software


Introducción

Durante el ciclo de vida de un software, es común que después de la implementación se requiera dar un cierto tipo de mantenimiento para que su calidad no se reduzca,  o simplemente deje de ser útil debido a las nuevas tecnologías entre otras cosas.

Muchas empresas que utilizan software como un sustento en sus metodologías de trabajo, han implementado diversas estrategias para reducir el coste en cuanto a software; llegando a un punto en el que deben de tomar una decisión y definir cuáles de las aplicaciones que utilizan deben ser eliminadas o sencillamente aplicarles mantenimiento. Aunque es muy cierto que el software debería ser lo suficientemente bueno para que no necesitara cambios una vez que sale de fábrica, sin embargo, aproximadamente un 40% del software instalado deber ser revisado (Sánchez, 2011).

Mantenimiento de Software

Para poder entrar en más detalle con respecto al tema, es necesario conocer el significado de mantenimiento.

“Es el conjunto de actividades que se ejecutan por el personal adecuado, capacitado en diferentes especialidades técnicas para efectuar los diferentes trabajos correspondientes de compostura y reparaciones de equipos, instalaciones e inmuebles.” (Mejia Campos & Zamorano Porras, 2013)

Varios autores toman como clasificación diferentes tipos de mantenimiento, por lo general toman una categorización de tres tipos pero en esta ocasión definiremos cuatro como los esenciales:

1.       Mantenimiento Correctivo
2.       Mantenimiento Adaptativo
3.       Mantenimiento Perfectivo
4.       Mantenimiento Preventivo

Ilustración 1.- Distribución del esfuerzo de Mantenimiento (Sommerville, 2005)



Mantenimiento Correctivo

Mantenimiento para reparar defectos del software. Por lo general, los errores de código son relativamente baratos de corregir, los errores de díselo son mucho más caros ya que implican reescribir varios componentes de los programas. Los errores de requerimientos son los más caros de reparar debido a que puede ser necesario un diseño extenso del sistema. (Sommerville, 2005)

Mantenimiento Adaptativo

Mantenimiento para adaptar el software a diferentes entornos operativos. Este tipo de mantenimiento se requiere cuando cambia algún aspecto del entorno del sistema, como por ejemplo el hardware, la plataforma del sistema operativo u otro software de soporte. El sistema de aplicaciones debe modificarse para adaptarse a estos cambios en el entorno. (Sommerville, 2005)

Mantenimiento Perfectivo

Mantenimiento para añadir o modificar las funcionalidades del sistema. Este tipo de mantenimiento es necesario cuando los requerimientos del sistema cambian como respuesta a cambios organizacionales o del negocio. La escala de los cambios requeridos en el software es a menudo mucho mayor que en los otros tipos de mantenimiento. (Sommerville, 2005)


Mantenimiento Preventivo

Consiste en la revisión periódica de ciertos aspectos, tanto de hardware como de software. El propósito es prever averías o desperfectos en su estado inicial y corregirlas para mantener un funcionamiento óptimo. Por lo regular este tipo de mantenimiento es el más elevado en cuanto a costos y por esta razón en muchas ocasiones prefieren excluirlo.

Conclusión

Debido a las circunstancias es más factible para muchas empresas optar por aplicar mantenimiento a sus sistemas, en lugar de generar uno nuevo. Gracias a esto se logran evitar grandes costos, sin embargo a la larga se verán reflejados algunas desventajas que hacen que el mantenimiento se vuelva obsoleto para poder continuar con la utilidad del software.

Trabajos citados

Mejia Campos, F., & Zamorano Porras, I. (2013). Instituto de ciencias básicas e ingeniería. Recuperado el 01 de 02 de 2014, de Universidad Autónoma del Estado de Hidalgo: http://www.uaeh.edu.mx/docencia/Tesis/icbi/licenciatura/documentos/Software%20de%20mantenimiento.pdf
Sánchez, D. (31 de Julio de 2011). Mantenimiento de software: un análisis automatizado de las aplicaciones es decisivo para reducir costes. Computerworld, 10-11.

Sommerville, I. (2005). Ingeniería del Software. Madrid: Pearson Eduacion.

Descarga formato PDF:





viernes, 29 de noviembre de 2013

Sistema Distribuido (Lexuz)

Lexuz, es un software de apoyo didáctico, que sirve de herramienta para terapeutas y docentes con el fin de ayudar con el tratamiento de intervención a niños de 4-8 años de edad con problemas de dislexia, desarrollado exclusivamente para la Clínica Universitaria de Salud Integral (CUSI) ubicado en las instalaciones de la Facultad de Estudios Superiores Iztacala (FESI) de la Universidad Nacional Autónoma de México (UNAM).

Durante el curso de Sistemas Distribuidos hemos aprendido diferentes conceptos muy importantes pertenecientes al área de cómputo, y entre ellas, nuestra propia definición de un sistema distribuido: "Sistema en el cual computadoras independientes, interconectados por una red, se comunican a través de mensajes siguiendo protocolos para interactuar entre ellos y así alcanzar un objetivo en particular."

Es por ello, que la justificación de "Lexuz" como un sistema distribuido se fundamenta principalmente en lo siguiente: 

Lexuz es distribuido porque se compone de un servidor, en el cual se encuentra la base de datos y el programa ejecutándose, y de varios clientes, desde donde se puede accesar al sistema sin necesidad de tener la base de datos o el programa ejecutándose en la maquina cliente.

Esto se logra ya que se comunican utilizando la IP del servidor, se conectan a este y pueden obtener información generada por otra maquina cliente y ejecutar procesos.

El software se utilizará de forma tal que estén conectadas en una red local, por lo que la conexión que se estableció es de forma Cliente-Servidor. Esto cumple la parte de "Interconectados por una red" de nuestra definición.

Siguiendo un protocolo establecido, la máquina Cliente es capaz de solicitar información a la máquina Servidor, que posteriormente se lo regresará para completar la comunicación y la interacción entre ellas, esto se puede analizar claramente a la hora de contestar un formulario.

Una vez contestado los formularios, se habrá alcanzado el objetivo del modulo de este software, ya que la información habrá sido automatizada para lograr una facilidad al usuario y a su campo de trabajo.

Después de percibir todos los puntos anteriores, concluyó que "Lexuz" cumple con los requisitos mínimos para considerarse un sistema distribuido.

miércoles, 20 de noviembre de 2013

Juego orientado a Sistemas Distribuidos (Ahorcado)

El juego de "El ahorcado" es un juego de lápiz y papel, en el que el objetivo es adivinar una palabra o frase.

En este ocasión hemos automatizado el juego. Al comenzar aparecerá un "muñequito" formado por caracteres ASCII, y una raya en lugar de cada letra de la palabra a adivinar.

Instrucciones de juego


Luego el jugador deberá intentar adivinar las letras que le parece que puede contener la palabra, y una por una  ir ingresando mediante el teclado, seguido de un enter cada letra, que crea el usuario sea la correcta. Si acierta, se escriben todas las letras coincidentes. Si la letra no está,  se elimina una parte del cuerpo del "muñequito".  La cantidad de errores o de fallas permitidas antes de completar el cuerpo son un máximo de seis. Se gana el juego si se completa la palabra, y se pierde si se elimina el cuerpo antes de terminar la palabra.

Clases Utilizadas


ClienteAhorcadoint.java  (Interfaz)



public interface ClienteAhorcadoint{

    public  void enviarMensaje();
public  String crearMensajeRespuesta();
public  int getEstadoJuego();
public  char getLetra();
public  int getNroIntentos();
public  String getPalabraEnProgreso();
public  void setEstadoJuego(int estadoJuego);
public  void setLetra(char letra);
public  void leerMensaje(String mensaje);
public  void imprimirMensajeEnPantalla();
public String getPalabraActualGuionBajo();
public  String mostrarEstado();
public  void imprimirEntrada();
public  void imprimirSalida();
}

Servidor.java 



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

public class Servidor {
//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 = 10026;
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", "señal","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", "señal","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 NOHABER 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(Servidor.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) {
           Servidor.SocketDisponible = SocketDisponible;
}
public static void setConexionesRealizadas(int conexionesRealizadas) {
          Servidor.conexionesRealizadas = conexionesRealizadas;}
 
public static void setEstadoJuego(int estadoJuego) {
          Servidor.estadoJuego = estadoJuego;}
 
public static void setLetra(char letra) {
          Servidor.letra = letra;}
 
public static void setNroIntentos(int nroIntentos) {
          Servidor.nroIntentos = nroIntentos;}
 
public static void setPalabra(String palabra) {
          Servidor.palabra = palabra;}
 
public static void setPalabraEnProgreso(String palabraEnProgreso) {
           Servidor.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());}
}

Cliente.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;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.JOptionPane;

public class Cliente extends JFrame implements ClienteAhorcadoint{

private static final int Juego_inactivo = 0;
private static final int Juego_Activo = 1;
private static final int GANO = 2;
private static final int PERDIO = 3;
private static final int Solicitud_con = 4;
private static final int Juego_fin = 5;
//ATRIBUTOS DE LA CONEXION
private static final int puerto = 10028;
private static BufferedReader in = null;
private static DataOutputStream out = null;
private static Socket conexion;
public static Cliente aux;
//ATRIBUTOS DEL JUEGO
private static String letra_enviar="";
private static int estadoJuego = Juego_inactivo;
private static int intentosRestantes = 6;
private static char letra = '*';
private static String palabraEnProgreso = "*";
private static Integer nroMensaje = 0;

public static  ImageIcon image0 = new ImageIcon("Intento_0.jpg");
public static  JLabel label_intento0 = new JLabel("", image0, JLabel.CENTER);
public static  ImageIcon image1 = new ImageIcon("Intento_1.jpg");
public static  JLabel label_intento1 = new JLabel("", image1, JLabel.CENTER);
public static  ImageIcon image2 = new ImageIcon("Intento_2.jpg");
public static  JLabel label_intento2 = new JLabel("", image2, JLabel.CENTER);
public static  ImageIcon image3 = new ImageIcon("Intento_3.jpg");
public static  JLabel label_intento3 = new JLabel("", image3, JLabel.CENTER);
public static  ImageIcon image4 = new ImageIcon("Intento_4.jpg");
public static  JLabel label_intento4 = new JLabel("", image4, JLabel.CENTER);
public static  ImageIcon image5 = new ImageIcon("Intento_5.jpg");
public static  JLabel label_intento5 = new JLabel("", image5, JLabel.CENTER);
public static  ImageIcon image6 = new ImageIcon("Intento_6.jpg");
public static  JLabel label_intento6 = new JLabel("", image6, JLabel.CENTER);

public static JLabel Ingrese;
public static JTextField txt_letra;
public static JButton enviar;

public Cliente() {

setTitle("Juego Ahorcado");
setSize(394, 280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout dis = new FlowLayout();
setLayout(dis);

add(label_intento0);
add(label_intento1);
add(label_intento2);
add(label_intento3);
add(label_intento4);
add(label_intento5);
add(label_intento6);

Ingrese=new JLabel ("Ingrese letra: "); //label de Ingrese letra
Ingrese.setBounds(15,330,150,27);
//add(Ingrese);

txt_letra=new JTextField(""); //cuadro donde se ingresa la letra
txt_letra.setColumns(10);
txt_letra.setBackground(new java.awt.Color(251,248,248));
//add(txt_letra);

enviar=new JButton ("Enviar"); // Enviar
enviar.setBounds(360,330,140,25);
enviar.setToolTipText("Enviar letra");
//add(enviar);

label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(true);
label_intento6.setVisible(false);


 setVisible(true);
 enviar.addActionListener(oyente);
}

public static void main(String[] args) {
     
try {

conexion = new Socket("192.168.0.48", 10028);
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 Exitosa...");
aux = new Cliente();
boolean jugando = true;
Cliente app = new Cliente();
while (jugando == true) {
if (estadoJuego == Juego_inactivo) {
aux.setEstadoJuego(Solicitud_con);
aux.enviarMensaje();
// imprimirSalida();
} else {
  //LEER MENSAJE DESDE SERVIDOR
  aux.leerMensaje(in.readLine());
  // imprimirEntrada();
if (estadoJuego == Juego_Activo) {
//IMPRIMIR MENSAJE EN PANTALLA Y LEER UNA LETRA DEL CLIENTE
aux.imprimirMensajeEnPantalla();
System.out.println("Por favor ingrese una letra: ");
//SETEAR LA LETRA LEIDA POR EL CLIENTE

aux.setLetra(entradaUsuario.readLine().charAt(0));
aux.enviarMensaje();
} else {
 if (estadoJuego == GANO) {
aux.setEstadoJuego(Juego_fin);
aux.imprimirMensajeEnPantalla();
jugando = false;
System.out.println("¡¡¡Congratulations!!!");
System.out.println("Has ganado el juego :)");
 }
 if (estadoJuego == PERDIO) {
 aux.setEstadoJuego(Juego_fin);
 aux.imprimirMensajeEnPantalla();
 jugando = false;
 System.out.println("No quedan mas intentos");
 System.out.println("Has perdido");
 }
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 esteinactivo.");
  }
    }

ActionListener oyente=new ActionListener(){
        public void actionPerformed(ActionEvent evento){

             if (evento.getSource() == enviar)
            {
                aux.setLetra(txt_letra.getText().charAt(0));
            }
}
};

public  void enviarMensaje() {
 
  try {
     if (estadoJuego == Solicitud_con) {
    out.writeBytes(aux.crearMensajeRespuesta());
} else {
out.writeBytes(aux.crearMensajeRespuesta());
}
}catch (IOException iOException) {
   System.out.println("ERROR AL ENVIAR EL MENSAJE");
}}

public  String crearMensajeRespuesta() {
    return estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso + "#" +nroMensaje + "\n";
}

public  int getEstadoJuego() {
    return estadoJuego;}

public  char getLetra() {
    return letra;
}

public  int getNroIntentos() {
    return intentosRestantes;
}

public  String getPalabraEnProgreso() {
    return palabraEnProgreso;
}

public  void setEstadoJuego(int estadoJuego) {
    Cliente.estadoJuego = estadoJuego;
}

public  void setLetra(char letra) {
    Cliente.letra = letra;
}

public  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());
}}

public  void imprimirMensajeEnPantalla() {
   
    //IMPRIMIENDO MENSAJE EN PANTALLA
System.out.println("¨¨¨¨¨¨¨¨ JUEGO EL AHORCADO ************");
imprimirAhorcado(intentosRestantes);
System.out.println("\nPALABRA ACTUAL: " + aux.getPalabraActualGuionBajo());
System.out.println("INTENTOS RESTANTES: " + intentosRestantes);}

public  String getPalabraActualGuionBajo() {
    String[] a = palabraEnProgreso.split("");
String impr = "";
for (int i = 0; i < a.length; i++) {
   impr += a[i] + " ";}
return impr;}

public  String mostrarEstado() {
    if (estadoJuego == 0) {
   return "Juego_inactivo";}
    else {
   if (estadoJuego == 1) {
return "Juego_Activo";}
else {
   if (estadoJuego == 2) {
return "GANO";}
else {
   if (estadoJuego == 3) {
return "PERDIO";}
else {
   if (estadoJuego == 4) {
return "Solicitud_con";}
else {
   return "Juego_fin";}}}}}}

public  void imprimirEntrada() {
   
    String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso +"#" + nroMensaje;
System.out.println("LEIDO POR CLIENTE: " + a + "\n" + aux.mostrarEstado());}

public  void imprimirSalida() {
   
    String a = estadoJuego + "#" + intentosRestantes + "#" + letra + "#" + palabraEnProgreso +"#" + nroMensaje;
System.out.println("ENVIADO POR CLIENTE: " + a + "\n" + aux.mostrarEstado());}

public  void imprimirAhorcado(int intentosRestantes) {
if (intentosRestantes < 1) {
   label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(true);
}
else {
   if (intentosRestantes < 2) {
   label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(true);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 3) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(true);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 4) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(true);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 5) {
label_intento0.setVisible(false);
label_intento1.setVisible(false);
label_intento2.setVisible(true);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
label_intento5.setVisible(false);
}
else {
    if (intentosRestantes < 6) {
label_intento0.setVisible(false);
label_intento1.setVisible(true);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);
}
else {
    if (intentosRestantes < 7) {
label_intento0.setVisible(true);
label_intento1.setVisible(false);
label_intento2.setVisible(false);
label_intento3.setVisible(false);
label_intento4.setVisible(false);
label_intento5.setVisible(false);
label_intento6.setVisible(false);

}}}}}}}
}
}

Conclusión:


Los sockets son basicamente formas en las que podemos interconectar 2 (o mas) programas mediante el uso de la internet. En java se utilizan para poder crear conexiones utilizando basicamente una IP/hostname y un puerto para establecer la conexión, en base a esto,  podemos realizar un sin fin de aplicaciones, que van desde sencillos juegos, ventanas de chat, hasta complejas actividades como administrar varias computadoras a la vez.

El modelo mas basico de los sockets consta de 2 simples programas, un servidor y un cliente. Basicamente el programa servidor comienza a “escuchar” en un puerto determinado(nosotros lo especificamos), y posteriormente el programa que la hace de “cliente” debe conocer la ip o nombre de dominio/hostname del servidor y el puerto que esta escuchando, al saber esto simplemente solicita establecer una conexión con el servidor. Es aqui cuando el servidor acepta esa conexión y se puede decir que estos programas estan “conectados”, de este modo pueden intercambiar información. 

domingo, 8 de septiembre de 2013

El Modelo OSI

 Por mucho tiempo se consideró al diseño de redes un proceso muy complicado de llevar a cabo, esto es debido a que los fabricantes de computadoras tenían su propia arquitectura de Red y esta era muy distinta al resto, luego los fabricantes consideraron acordar una serie de normas internacionales para describir la arquitectura de redes.

El modelo de Referencia Osi: Open System Interconnection es una propuesta de la Organización Internacional de Normalización (ISO: International Organization for Standardization) lanzada en 1984 en la que se plantea como sería la comunicación de unos sistemas con otros distintos, de ahí que el nombre sea “Interconexión de Sistemas Abiertos”.

Este modelo está dividida en 7 capas, cada una representa cada una de las tarea de la Red por lo que cada capa tiene funciones bien diferenciadas de las demás, a continuación describiremos brevemente cada capa.
Siete capas del Modelo OSI.


Las siete capas del modelo se apilan de la siguiente manera, comenzando con el 'inferior' en la jerarquía (físico) y proceder a la 'mejor' (la aplicación).

  • Aplicación
  • Presentación
  • Sesión
  • Transporte
  • Red
  • Vínculo de datos
  • Física





Capa Física.

La capa inferior del modelo OSI, se ocupa de la transmisión y recepción de la secuencia de bits sin formato no estructurado a través de un medio físico. Describe las interfaces eléctricas ópticas, mecánicas y funcionales en el medio físico y lleva a cabo las señales para todos los niveles superiores.

Se tiene en cuenta el diseño de red, cables y conectores, majeo de tensiones, etc. Básicamente es el canal de comunicación y el cómo se transmite por éste.

Capa Enlace.

En la segunda capa, o nivel de Enlace, hablamos ya de una Unidad mínima de datos llamada “Tramas”. Se plantea la Detección y corrección de errores que se puedan producir en la comunicación también se encarga de evitar que un receptor lento se sature en caso de estar recibiendo demasiada información y además reparte la utilización de la red cuando se trata de un medio compartido

Capa de Red.

En la tercera capa, o nivel de red, la unidad de información recibe el nombre de “Paquetes”. Básicamente en esta capa se determina la mejor ruta para el envío de información, caminos cortos, más rápidos, etc.  Y además se encarga de convertir y adaptar los mensajes que circulan por redes heterogéneas

Capa de Transporte.

En la cuarta capa, o nivel de transporte, la función básica es tomar los datos del nivel de sesión y pasárselos al de red asegurando que lleguen al nivel de sesión del otro extremo  garantiza que los mensajes se entregan sin errores, en secuencia y sin pérdidas o duplicaciones

Capa de Sesión

La quita capa, o nivel de sesión, es como el nombre indica donde se establecen esas conexiones o sesiones entre dos extremos para el intercambio de datos y además aquí es donde están los servicios de reanudación de conexiones ante posibles interrupciones o fallos.

Capa de Presentación.

En la sexta capa, o nivel de presentación podríamos resumir sus funciones como:
Controlador del significado de la información que se transmite de manera que aunque dos equipos puedan representar una información de distinta forma los datos que se envían por la red, ha de ser reconocible por los dos.

Por ultimo también está la función de codificación o cifrado de datos, de manera que mejoramos la seguridad.

Capa de Aplicación.

En la séptima y última capa, o nivel de aplicación, actúa como la ventana de usuarios, es donde se produce el contacto directo con el programa y es aquí donde se encuentran protocolos de intercambio de información como los de correo electrónico, envió de archivos, etc.


Por ultimo debemos saber que los datos al ir pasando de capa en capa se van añadiendo o quitando cabeceras dependiendo si  estamos enviando o recibiendo. Si queremos enviar un dato cada vez que pase por una capa se le añadirá una cabecera nueva así hasta llegar a la otra estación donde para leer la información tendrá que ir quitándole las cabeceras según pase por las distintas capas hasta llegar al programa


Conclusión.

EL modelo OSI es muy util debido a que sirve como referencia para entender la complejidad del estudio y diseño de redes, este modelo nos sirve para visualizar los datos, desde programas básicos de aplicación que usamos a diario a través de una red debido a que lo que hace es permitir ver a todos los usuarios de la red ver el funcionamiento entre capa y capa.

Bibliografía

Laboratorio TecnoKu. (04 de Diciembre de 2012). Modelo OSI (Simplificado - Explicación breve). Recuperado el 08 de Septiembre de 2013, de http://www.youtube.com/watch?v=We8nONBHk3Q
Microsoft. (2002 de Febrero de 2002). The OSI Model's Seven Layers Defined and Functions Explained. Recuperado el 08 de Septiembre de 2013, de Microsoft Soporte : http://support.microsoft.com/kb/103884/es


Descarga PDF: