sábado, 19 de abril de 2014

Programación de Red - JAVA ( 6. Programación de sockets: Más allá de los protocolos estándar)

Contenidos:

  1. Introducción: Como funciona la comunicación en red.
  2. Leyendo desde una URL : Hora de conectar y leer de Internet.
  3. Programar Java para conectar a servidores proxy HTTP.
  4. A descargar contenido de Internet.
  5. Cotización en bolsa: Un programa aplicando lo aprendido.
  6. Programación de sockets: Más allá de los protocolos estándar.

6. Programación de sockets: Más allá de los protocolos estándar.


Esta parte de Java es una de las más emocionantes; o por lo menos eso fue para mi cuando empecé a conocer los Sockets; ya que estos permiten especificar en cierta medida tu propia forma de comunicación entre cliente y servidor. Esta capacidad de poder definir tu forma de comunicación te permite enviar solo los datos necesarios, reduciendo los encabezados o eliminándolos completamente. Como consecuencia la comunicacion por socket es menos pesada que la comunicación con protocolos estandar; ademas la comncicacion por socket es bireccional ( flujo de bites doble); al contrario de lo que sucede en la comunicacion basada en solicitudes y respuestas.

En java tenemos las clases Socket y ServerSocket del paquete java.net para trabajar con socket "normales"; digo normales por que también existe la posibilidad de los Socketc SSL que conectan de forma segura con https y certificados, pero que en este artículo pasaremos de largo sobre el tema...intentaré hablar sobre sockets SSL en otro artículo.

Un socket es una conecxion en un extremo de una red IP. La direccion de un socket contiene una IP y un puerto. Cuando instanciamos la clase ServerSocket se crea un servidor que se ejecuta en memoria y escucha las solicitudes de cliente ( otros programas que se conectarán con Socket ).
El programa cliente debe crear una instancia de Socket ( el socket cliente ) que apunte a la direcciín IP y puerto del ServeSocket que está ejecutándose.

Los puertos recomendados para un ServerSocket son los mayor a 1024 para evitar conflictos con programas del sistema. Algunos puertos conocidos son : 8080 para HTTP, 443 para HTTPS, 21 para FTP, 389 para LDPA, etc.

Para poder intercambiar datos; tanto el cliente como el servidor deben obtener referencias a flujos de entrada y salida. Bueno y ahora vamos a lo nuestro, a lo que nos gusta.....¡¡¡ a programar !!!!

Vamos a ver un ejemplo muy bien comentado escrito en NetBeans donde se programa por un lado el servidor y por otro el cliente. Consiste en que el cliente se conecta al servidor para solicitar un dato, en nuestro ejemplo el precio de un producto. Nuestro servidor buscará el precio y le devuelve el resultado al cliente. Claro que para ejemplo nos bastará con generar un número aleatorio que represente el precio solicitado, en una aplicación real el almacen de datos para obtener el precio podría ser una base de datos de productos

El Servidor:

package com.pelusadev.programacionenlared;

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


/**
 *
 * @author pelusadev
 */

public class Servidor {

public static void main(String[] arg)
{
     ServerSocket serverSocket;
     Socket cliente;

     BufferedReader entrante = null;
     OutputStream saliente = null;

     try {
          // Creamos el socket server escuchando en el puerto 4000
             serverSocket = new ServerSocket(4000);
             System.out.println("Esperando a que los clientes consulten precios");
             while(true)
             {
                // Esperar la solicitud
                cliente = serverSocket.accept();
                 
                // Obtenemos los flujos
                entrante = new BufferedReader(new InputStreamReader(cliente.getInputStream()));      
                saliente = cliente.getOutputStream();
               
                // Recibimos el nombre del producto que se desea consultar;
                String nombreProducto = entrante.readLine();
        
               // Generamos un precio aleatorio
               Double precioAleatorio = new Double(Math.random()*100);
               String precio = precioAleatorio.toString();
         
               // Escribimos la salida
               byte[] mensajeDeSalida = ("El precio del producto " + nombreProducto + " es "+precio).getBytes();
               saliente.write(mensajeDeSalida);
             }
         } catch (IOException ex) {
             Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
         }finally{
          try{
              entrante.close();
              saliente.close();
          }catch(Exception ex){
              System.out.println("Error en el servidor: " + ex);
          }
        }
   }
}
El Cliente:

package com.pelusadev.programacionenlared;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 *
 * @author pelusadev
 */
public class Cliente {
    
    public static void main(String[] arg)
    {
        OutputStream salida = null;
        BufferedReader entrada = null;
    
        Socket clienteSocket=null;
        
        try{
            // Abrimos una conexión socket cliente
            clienteSocket = new Socket("localhost",4000);
            
            System.out.println("Cliente: " + clienteSocket);
            
            // Obtenemos los flujos
            salida = clienteSocket.getOutputStream();
            entrada = new BufferedReader(new InputStreamReader(clienteSocket.getInputStream()));
            
            // Enviar el nombre del producto al servidor
            salida.write(("GoogleGlass"+"\n").getBytes());
            salida.write(("Final"+"\n").getBytes());
            
            String respuesta;
            while(true)
            {
                respuesta = entrada.readLine();
                if(respuesta.equals("Fin"))
                {
                    break;
                }
                System.out.println("Precio: " + respuesta);
            }
        }catch(UnknownHostException uhe){
            System.out.println("UnknownHostException: " + uhe);
        }catch(IOException ex){
            System.out.println("IOException: " + ex);
        }finally{
            try{
                // Cerramos los flujos
                salida.close();
                entrada.close();
                clienteSocket.close();
            }catch(IOException e){
                System.out.println("No se puede cerrar la conexión: " + e.getMessage());
            }            
        }        
    }
}

Ejecución del servidor:


Ejecución del Cliente


Descárgate la clase Servidor
Descárgate la clase Cliente

No hay comentarios:

Publicar un comentario