domingo, 19 de julio de 2015

Servidor Multihilo con Java

Un servidor multihilo es aquel que puede aceptar muchas solicitudes simultaneas. Ésta entrada describe un servidor multihilo simple implementado en Java. Para hacerlo basta con implementar un Servidor con sockets de la forma tradicional y agregar una pequeña modificación. Ahora usaremos el método ssock.accept()  de la clase Socket y el método MultiThreadServer(socketname) de la calse ServerSocket.


import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer implements Runnable {
   Socket csocket;
   MultiThreadServer(Socket csocket) {
      this.csocket = csocket;
   }

   public static void main(String args[]) 
   throws Exception {
      ServerSocket ssock = new ServerSocket(1234);
      System.out.println("Escuchando");
      while (true) {
         Socket sock = ssock.accept();
         System.out.println("Conectado");
         new Thread(new MultiThreadServer(sock)).start();
      }
   }
   public void run() {
      try {
         PrintStream pstream = new PrintStream
         (csocket.getOutputStream());
         for (int i = 100; i >= 0; i--) {
            pstream.println(i + 
            " Hola");
         }
         pstream.close();
         csocket.close();
      }
      catch (IOException e) {
         System.out.println(e);
      }
   }


Ventajas de un servidor Multihilo

Las ventajas se pueden resumir en dos aspectos:
1.Peticiones de clientes que duran mucho, no bloquean el servidor.
2.Se gasta menos tiempo afuera de la llamada de accept()

Un un servidor de un solo hilo. Los clientes que toman mucho tiempo podrian provocar que el servidor no responda por un largo periodo de tiempo, esto no sucede para un servidor multihilo.

Para establecer la conexión requerimos de nuestro cliente. Este es el codigo fuente tomar en cuenta el ingreso de argumentos en Socket().


public static void main(String[] args) throws IOException {

        //Socket para establecer conexion
        Socket cliente = new Socket(args[0], Integer.parseInt(args[1]));
        //Enlazar entrada de datos con UN FLUJO
        BufferedReader lecturaCliente=new BufferedReader(new InputStreamReader(cliente.getInputStream()));
        //Entrada de datos de usuario
        BufferedReader lecturaTeclado=new BufferedReader(new InputStreamReader(System.in));
           
        //Enlazar salida de datos con un flujo
        PrintWriter escrituraCliente=new PrintWriter(cliente.getOutputStream(),true);
        //variable String para alamcenar mensaje recibido
        String mensajeEnviar =new String();
        //escuchar por mensajes
        while((mensajeEnviar=lecturaTeclado.readLine())!=null){
            //System.out.println("Mensaje devuelto" + mensajeEnviar);
            escrituraCliente.println(mensajeEnviar);
        }
        cliente.close();
        
    }

}

domingo, 28 de junio de 2015

Archivos, Flujos y Serialización de Objetos.

Introducción

Nuestras computadoras y dispositivos móviles utilizan información "persistente" para almacenar datos a largo plazo, ésta información persistente se conoce como archivos y está disponible incluso después que se termina la ejecución del programa. Los archivos se almacenan por lo general en dispositivos de almacenamiento no volátiles secundarios como los discos duros o los SSD.

Archivos y Flujos

 Java "ve" cada archivo como un flujo secuencial de bytes, cada sistema operativo provee un mecanismo para saber cual es el final de un archivo, éste puede ser un marcador de final de archivo o un conteo total de bytes en el mismo.
Los flujos binarios representan datos en formato binario, y los flujos de caracteres manejan datos como secuencia de caracteres.

Serialización de objetos

Java provee éste mecanismo que permite objetos ser escritos o leidos desde un flujo.Un objeto serializado esta representado por como una secuencia de bytes que incluye la informacion.del objeto, como su tipo y el tipo de datos que almacena. Después que un objeto serializado se escribió en un archivo, puede ser leido y deserializado para recrear el objeto nuevamente.

Para qué sirven las clases ObjectInputStream y ObjectOutputStream? 

Posibilitan que objetos se lean o escriban por completos desde un flujo o un archivo.Solo las clases que implementan la interfaz Serializable pueden ser serializadas o deserializadas.
La interfaz ObjectOutput contiene el metodo writeObject, que toma   un objeto como argumento y escribe su información en OutputStream, Una clase que que implementa ésta interfaz como ObjectOutputStream, asegura que el objeto es Serializable.
La interfaz ObjectInput contiene el método readObject que lee y retorna una referencia a un objeto desde InputStream.Despues de la lectura, la referencia se puede hacer cast con el tipo real del objeto.
Se expone un ejemplo a continuación:

En este ejemplo, tenemos una clase Paciente, que nos permite crear (valga la redundancia) Objetos del tipo Paciente. Este tipo de datos posee atributos para almacenar información de documento de identificación, nombre y apellido, y finalmente su género. La clase provee constructores, getters y setters adecuados.





Aquí se crean ArrayLists, para organizar los datos, los pacientes y sus datos, se almacenan aquí.
Como se explicó previamente, para almacenar estos datos, hacen falta serializarlos, y luego enviarlos como un flujo para ser escritos en el archivo empleamos entonces las sentencias FileInputStream. ObjectInputStream, FileOutputStream, ObjectOutputStream.

El procedimiento basico a seguir es declarar un objeto de tipo FileOutputStream usando como parametro de entrada la ruta del archivo. Despues de eso Convertimos a un flujo Usando:
 ObjectOutputStream resultado=new ObjectOutputStream(fileOut);
y escribimos en el archivo con:resultado.writeObject(listaPacientes);
El proceso de lectura es analogo al de escritura.












domingo, 21 de junio de 2015

Excepciones en Java

Qué es una excepción?

Una excepción es una indicación de un problema que ocurre durante la ejecución de un programa.
El manejo de excepciones permite a los programadores crear aplicaciones que solucionan estas excepciones.

Cuando ocurre una excepción?

Las excepciones se lanzan cuando un método detecta un problema, y es incapaz de resolverlo. El "stack" de una excepción incluye el nombre de la excepción en un mensaje que indica el problema que ocurrió. El punto en el que las excepciones ocurren se llama "throw point".
Un ejemplo de excepción sería una división para cero.

Cuando usar manejo de excepciones?

Las excepciones solucionan errores que ocurren en tiempo de ejecución.

Jerarquía de Excepciones en Java

Todas las clases de excepciones heredan directa o indirectamente de la clase Exception, se puede extender la jerarquía con nuestras propias clases de excepciones. La superclase de la calse Exception es "Throwable"; solo los objetos de tipo "Throwable" pueden ser usados con el mecanismo de manejo de excepción.La clase Throwable tiene dos subclases: Exception y Error.
La clase Exception representa problemas que pueden ocurrir en un programa  de Java , y la clase Error representa errores que no son muy frecuentes y q normalmente no se capturan en la aplicación.

Creando nuestras propias Excepciones.

Una nueva excepción debe extender una excepción existente para asegurar que la clase se puede usar con un mecanismo de manejo de la excepción.
Definimos una Excepción extendiendo de Exception.
Ejemplo:








Interfaces en Java

Antes de empezar puedes descargar el proyecto haciendo clic AQUI.

Qué es una interfaz?

Una interfaz es un conjunto de métodos abstractos y/o constantes, por lo tanto especifican que operaciones se deben realizar, pero no indican como se llevan a cabo.

Como declarar una interfaz?

La declaración de una interfaz empieza con la palabra interface, todos los miembros de una interfaz den ser públicos, y no se provee ninguna implementación como lo son las variable de insgancia (atributos) o métodos concretos.

Como implementar una interfaz?

Para usar una interfaz, una clase concreta debe implementar todos los métodos de la interfaz, Se usa la palabra implements, seguido del nombre de la interfaz para indicar que se implementa la misma.
En el caso de no implementar todos los métodos, debemos declarar nuestra clase como abstract.

Por qué usar interfaces?

La sinterfaces se usan cuando clases que no se relacionan o no tienen nada en común, requieren compartir métodos idénticos, de éste modo podemos procesar polimórficamente nuestras clases.
Esposible crear interfaces que describan en forma general la funcionalidad, y luego crear clases que implementen dicha funcionalidad.

Interfaces de Java y ordenar datos de un ArrayList

 Como ya se explicó, podemos crear una interfaz y e implemntarla posteriormente en clases concretas. Java posee muchas interfaces predefinidas. Para este ejemplo usaremos compareTo, al que le vamos a proveer de implementación para ordenar datos de un ArrayList.
De seguro te preguntas por qué proveer una implementación de éste método en lugar de crear uno propio, lo hacemos porque existen otras clases que dependen de los argumentos que retorna éste método. Lo que hacemos cuando editamos éste método es "enseñarle a Java" como determinar qué parámetro es mayor. De ese modo se pueden realizar otras operaciones, como ordenamiento de un ArrayList de objetos.

Ejemplo

Vamos a crear  una aplicacion que crea estudiantes con atributos de ID(numero unico), nombre, fecha de nacimiento y rendimieto academico (IRA). existe otra clase llamad Curso, que almacena los estudiantes en un Arraylist de tipo Estudiante.

Primero la clase que define el tipo de datos Estudiante:
Esta parte del codigo define únicamente atributos, getters y setters:


Para ordenar los datos se requiere sobreescribir el método compareTo:



La segunda parte la constituye la case Curso, en la cual se almacenan y organizan los datos. Nótese el uso de Collections.sort(listaEstudiantes). Esté método recibe como parámetro de entrada el ArrayList, pero para realizar el ordenamiento depende de nuestra sobreescritura del método compareTo en la clase Estudiante.



Solo hace falta una clase aplicación que ponga a prueba nuestra implementación de la interfaz.


Obtenemos una salida como esta:



Otra Interfaz importante : cloneable

Que es un clon?

Un clon de un objeto es otro objeto con una identidad distinta pero con el mismo contenido. Para definir un clon, una clase  debe implementar cloneable y debe sobreescribir el metodo Object's clone con un modificador público. 

Que es necesario para clonar un objeto?

Los objetos que pueden ser clonados deben ser una instancia de una clase que implementa la intefaz cloneable.  Si una clase permite a los clientes clonar sus instancias debe sobreescribir al método Object's clone con un modificador público.

Por qué usar la interfaz cloneable?

Cuando un objeto es copiado a otro usando el operador de asignación, solo se copia la referencia de dicho objeto, lo que significa que los cambios en un objeto, se ven reflejados en el otro también.
El método clone(), copia el contenido de un objeto a otro, pero hay que ser cuidadosos, porque podriamos copiar una referencia contenida en el otro objeto.
Ejemplo:
Primero una calse para realizar el proceso de clonación, se utiliza manejo de excepciones.


Luego una clase para poner a prueba el manejo de excepciones.










martes, 7 de abril de 2015

Primer programa con Java: Hola Mundo

Se explica sintaxis y  proceso para compilar un programa básico de Java usando cmd de Windows y la terminal de Linux Bash.
Antes de empezar necesitarás descargar el JDK (Java Development Kit) , lo puedes descargar aquí, solo debes elegir la arquitectura de tu sistema y aceptar los términos de Oracle.

Hola Mundo



El programa se puede escribir en un bloc de notas, copia este texto en un archivo nuevo y almacénalo, debes recordar el directorio del mismo mas adelante (toma en cuenta que el nombre del archivo y el nombre del programa deben coincidir).

Compilación y Ejecución en cmd

En el símbolo del sistema (Inicio -> Todos los programas -> Accesorios -> Simbolo del sistema), escribimos el comando "cd " seguido del directorio donde guardaste el archivo HolaMundo.java por ejemplo en mi caso:  c:\Users\Christian\Desktop\HolaMundo.java. De ese modo estaríamos cambiando el directorio en el que estamos trabajando

A continuación escribimos en la consola "javac HolaMundo.java" (javac es el nombre del compilador javac.exe). Terminado este proceso, se habrá generado un archivo llamado "HolaMundo.class" que contiene el bytecode (el lenguaje de máquina de la máquina virtual de Java).

El bytecode debe ser transformado por la máquina virtual de java para ser ejecutado en nuestra computadora, para hacerlo escribimos en la ventana del Símbolo del Sistema: "java HolaMundo"




Compilación y Ejecución en Bash 

Utilizaremos el mismo código de la primera sección. En el caso de Linux (Ubuntu se ha usado para este tutorial) usaremos gedit, un editor de texto básico análogo a notepad. Copia el código que se muestra en la captura y almacénalo con el nombre "HolaMundo.java" (el nombre del programa debe coincidir con el nombre del archivo).  El proceso es similar al de la compilación en cmd, se escribe un comando para compilar y otro para interpretar con la máquina virtual de java.

Aquí una captura con el fragmento de código que requerimos




Para iniciar la compilación escribimos los comandos que se indican a continuación, el proceso consiste en cambiar el directorio (cd) seguido del directorio donde está almacenado el archivo del programa, compilar (javac) y ejecutar (java).
Ejecutar "javac", produce bytecode, el lenguaje de máquina de la JVM, para interpretar el mismo, se utiliza el comando "java".