No es un bug, es una característica no documentada

miércoles, 20 de enero de 2016

Procesos y servicios. Programación en red

TCP/IP

Nivel de Transporte


TCP: Protocolo basado en la conexión, garantiza que los datos enviados desde un extremo de la conexión llegan al otro extremo y en el mismo orden en que fueron enviados. De lo contrario, se notifica un error.

UDP: No está basado en la conexión como TCP. Envía paquetes de datos independientes, denominados datagramas, de una aplicación a otra; el orden de entrega no es importante y no se garantiza la recepción de los paquetes enviados.

Paquete java.net

Proporciona las clases para la implementación de aplicaciones de red. Se pueden dividir en dos secciones:
  • Una API de bajo nivel, que se ocupa de las abstracciones siguientes:
    • Las direcciones: Son los identificadores de red, como por ejemplo las direcciones IP.
    • Sockets: Son los mecanismos básicos de comunicación bidireccional de datos.
    • Interfaces: Describen las interfaces de red.
  • Una API de alto nivel, que se ocupa de las abstracciones siguientes:
    • URI: Representan identificadores de recursos universales.
    • URLs: Representan los localizadores de recursos universales.
    • Conexiones: Representa las conexiones al recurso apuntado por URL.

Clase InetAddress

Es la abstracción que representa una dirección IP (Internet Protocol).
Tiene dos subclases: Inet4Address para direcciones IPV4 en Inet6Address para direcciones IPv6; pero en la mayoría de los casos no es necesario recurrir a ellas.


Ejemplo:

Archivo TestInetAddress.java

import java.net.*;

public class TestInetAddress {
     
      public static void main(String[] args) {
           
            InetAddress dir = null;
            System.out.println("===========================================");
            System.out.println("SALIDA PARA LOCALHOST: ");
           
            try {
                  //LOCALHOST
                  dir = InetAddress.getByName("PC-ProfeB02");
                  pruebaMetodos(dir);
                 
                  //URL www.google.es
                  System.out.println("==========================================");
                  System.out.println("SALIDA PARA UNA URL:");
                  dir = InetAddress.getByName("www.google.es");
                  pruebaMetodos(dir);
                 
                  // Array de tipo InetAddress con todas las direcciones IP asignadas a google.es
                  System.out.println("\tDIRECCIONES IP PARA: " + dir.getHostName());
                  InetAddress[] direcciones = InetAddress.getAllByName(dir.getHostName());
                  for (int i = 0; i < direcciones.length; i++)
                        System.out.println("\t\t"+direcciones[i].toString());
                 
                  System.out.println("==========================================");
            } catch (UnknownHostException e1) {
                  e1.printStackTrace();
            }
     
      }// main
     
      private static void pruebaMetodos(InetAddress dir) {
           
            System.out.println("\tMetodo getByName(): " + dir);
            InetAddress dir2;
            try {
                  dir2 = InetAddress.getLocalHost();
                  System.out.println("\tMetodo getLocalHost(): " + dir2);
            } catch (UnknownHostException e) {
                  e.printStackTrace();
            }
           
            //USAMOS METODOS DE LA CLASE
            System.out.println("\tMetodo getHostName(): "+dir.getHostName());
            System.out.println("\tMetodo getHostAddress(): "+ dir.getHostAddress());
            System.out.println("\tMetodo toString(): " + dir.toString());
            System.out.println("\tMetodo getCanonicalHostName(): " + dir.getCanonicalHostName());   
     
      }//fin de pruebaMetodos

}//fin de TestInetAddress
     
En el ejemplo anterior se define un objeto InetAddress de nombre dir. En primer lugar lo utilizamos para obtener la dirección IP de la máquina local en la que se ejecuta el programa, en el ejemplo su nombre es PC-PROFEB02. A continuación llamamos al método pruebaMetodos() llevando el objeto creado. En dicho método se prueban los métodos de la clase InetAddress. Después utilizamos el objeto para obtener la dirección IP de la URL www.google.es y volvemos a invocar a pruebaMetodos() (para que funcione en este segundo caso necesitamos estar conectados a Internet). Por último utilizamos el método getAllByName() para ver todas las direcciones IP asignadas a la máquina representada por www.google.es. Se encierra todo en un bloque try-catch.

Clase URL

Represneta un puntero a un recurso en la Web. Un recurso puede ser algo tan simple como un fichero o un directorio, o puede ser una referencia a un objeto más complicado, como una consulta a una base de datos o a un motor de búsqueda.

En general una URL se divide en varias partes. Por ejemplo en la siguiente URL:


Constructores


Pueden lanzar la excepción MalformedURLException si la URL está mal construida.
No se hace ninguna verificación de que realmente exista la máquina o el recurso en la red.

Algunos métodos


Ejemplos:

En la siguiente clase vemos el uso de los constructores definidos anteriormente

Archivo Ejemplo1URL.java

import java.net.*;

public class Ejemplo1URL {
     
      public static void main(String[] args) {
           
            URL url;
            try {
                  System.out.println("Constructor simple para una URL:");
                  url = new URL("http://docs.oracle.com/");   
                  Visualizar(url);
                 
                  System.out.println("Otro constructor simple para una URL:");
                  url = new URL("http://localhost/PFC/gest/cli gestion.php?S=3" );
                  Visualizar(url);
                 
                  System.out.println("Const. para protocolo +URL +director1o");
                  url = new URL("http", "docs.oracle.com", "/javase/7");
                  Visualizar(url);
                 
                  System.out.println("Constructor para protocolo + URL + puerto directorio:");
                  url = new URL("http", "docs.oracle.com", 80, "/javase/7");
                  Visualizar(url);
                 
                  System.out.println("Constructor para un objeto URL y un directorio:");
                  URL urlBase = new URL("http://docs.oracle.com/");
                  url = new URL(urlBase, "/javase/7/docs/api/java/net/URL.html");
                  Visualizar(url);
                  } catch (MalformedURLException e) {
                        System.out.println(e);
                  }
           
            }// fin de main
     
      private static void Visualizar(URL url) {
           
            System.out.println("\tURL completa: " + url.toString());
            System.out.println("\tgetProtocol()" + url.getProtocol());
            System.out.println("\tgetHost(): " + url.getHost());
            System.out.println("\tgetPort(): " + url.getPort());
            System.out.println("\tgetFile(): " + url.getFile());
            System.out.println("\tgetUserInfo()" + url.getUserInfo());
            System.out.println("\tgetPath(): " + url.getPath());
            System.out.println("\tgetAuthority(): " + url.getAuthority());
            System.out.println("\tgetQuery(): " + url.getQuery());
            System.out.println("==============================================");
           
      }// fin de Visualizar()
     
}// EjemplolURL

En el siguiente ejemplo creamos un objeto URL a la dirección http://www.elaltozano.es, abre una conexión con él creando un objeto InputStream y lo utiliza como flujo de entrada para leer los datos de la página inicial del sitio; al ejecutar el programa se muestra en pantalla el código HTML de la página inicial del sitio.

Archivo Ejemplo2URL.java

import java.net.*;
import java.io.*;

public class Ejemplo2URL {
     
      public static void main(String[] args) {
           
            URL url=null;
           
            try {
                  url = new URL("http://www.elaltozano.es");
            } catch (MalformedURLException e) {
                  e.printStackTrace();
            }
           
            BufferedReader in;
            try {
                  InputStream inputstream = url.openStream();
                  in = new BufferedReader(new InputStreamReader(inputstream));
                  String inputLine;
                  while ((inputLine = in.readLine()) != null)
                        System.out.println(inputLine);
                  in.close();
            } catch (IOException e) {
                  e.printStackTrace();
            }
           
      }// Fin de main

}//Fin de Ejemplo2URL

Clase URLConnection

Es una clase abstracta que contiene métodos que permiten la comunicación entre aplicaciones y una URL.

Para conseguir un objeto de este tipo se invoca al método openConnection(), con ello obtenemos una conexión al objeto URL referenciado.

Las instancias de esta clase se pueden utilizar tanto para leer como para escribir al recurso referenciado por la URL.

Puede lanzar la excepción IOException.

Algunos métodos



Ejemplo

Archivo Ejemplo1urlCon.java

import java.net.*;
import java.io.*;

public class Ejemplo1urlCon {
     
      public static void main(String[] args) {
           
            URL url=null;
            URLConnection urlCon=null;
           
            try {
                  url = new URL("http://www.elaltozano.es");
                  urlCon= url.openConnection();
                 
                  BufferedReader in;
                  InputStream inputStream = urlCon.getInputStream();
                  in = new BufferedReader(new InputStreamReader(inputStream));
                  String inputLine;
                  while ((inputLine = in.readLine()) != null)
                        System.out.println(inputLine);
                  in.close();
            }
            catch (MalformedURLException e) {e.printStackTrace();}
            catch (IOException e) {e.printStackTrace();
            }
           
      }//fin de main

}//Fin de Ejemplo1urlCon

En el anterior ejemplo se crea un objeto URL a la dirección http://www.elaltozano.es, se invoca al método openConnection() del objeto para crear una conexión y se obtiene un URLConnection. Después se abre un stream de entrada sobre esa conexión mediante el método getInputStream(). Al ejecutar el programa se muestra la misma salida que en el ejemplo anterior; sin embargo, este programa crea una conexión con la URL y el anterior abre directamente un stream desde la URL.

Scripts del lado del servidor

Archivo index.html

<html>
<body>
<form action="vernombre.php" method="post" >
      <p>Escribe tu nombre:
      <input name="nombre" type="text" size="15">
      </p>
      <p>Escribe tus apellidos:
      <input name="apellidos" type="text" size="15">
      </p>
      <input type="submit" name="ver" value="Ver">
</form>
</body>
</html>

Archivo vernombre.php

<?php      
      $nom=$_POST[nombre];   
      $ape=$_POST[apellidos];     
      echo "El nombre recibido es: $nom, y ";
      echo "los apellidos son: $ape ";
?>

Desde Java, usando la clase URLConnection, podemos interactuar con scripts del lado del servidor y podemos enviar valores a los campos del script sin necesidad de abrir un formulario HTML.

Nuestro programa tendrá que hacer lo siguiente:
  • Crear el objeto URL al script con el que va a interactuar.
  • Abrir una conexión con la URL, es decir obtener el objeto URLConnection.
  • Configurar la conexión para que se puedan enviar datos.
  • Obtener un stream de salida sobre la conexión.
  • Escribir en el stream de salida
  • Cerrar el stream de salida

En el siguiente ejemplo se puede ver esta interacción con el script del lado servidor.

Archivo Ejemplo2urlCon.java

import java.io.*;
import java.net.*;

public class Ejemplo2urlCon {
     
      public static void main(String[] args) {
           
            try {
                 
                  URL url = new URL("http://localhost/DAM2PSP/vernombre.php");
                  URLConnection conexion = url.openConnection();
                  conexion.setDoOutput(true);
                 
                  String cadena ="nombre=Maria Jesús&apellidos=Ramos Martin";
                 
                  //ESCRIBIR EN LA URL
                  PrintWriter output = new PrintWriter (conexion.getOutputStream());
                  output.write(cadena);
                  output.close();  //cerrar flujo
                 
                  //LEER DE LA URL
                  BufferedReader reader = new BufferedReader (new InputStreamReader(conexion.getInputStream()));
                  String linea;
                  while ((linea = reader.readLine()) != null) {
                        System.out.println(linea);
                  }
                  reader.close();//cerrar flujo
                 
            } catch (MalformedURLException me) {
                  System.err.println("MalformedURLException: " + me);
            } catch (IOException ioe) {
                  System.err.println("IOException: " + ioe);
            }
           
      }//fin de main
     
}//Ejemplo2urlCon

En el ordenador del profesor PC-ProfeB02 tenemos instalado un servidor web Apache y dentro de htcdocs tenemos la carpeta DAM2PSP con el script PHP vernombre.php.
Normalmente cuando se pasa información a algún script PHP, este realiza alguna acción y después envía la información de vuelta por la misma URL. Por tanto, si queremos ver lo que devuelve será necesario leer desde la URL.

En el tercer ejemplo de esta clase se pureban algunos de los métodos de la clase URLConnection.

Archivo Ejemplo3urlCon

import java.net.*;
import java.io.*;
import java.util.*;

public class Ejemplo3urlCon {
     
      @SuppressWarnings("rawtypes")
      public static void main(String[] args) throws Exception {
           
            String cadena;
            URL url = new URL("http://localhost/2014/vernombre.html");
            URLConnection conexion = url.openConnection();
           
            System.out.println("Direccion [getURL()]:" + conexion.getURL());
           
            Date fecha = new Date(conexion.getLastModified());
            System.out.println("Fecha ultima modificacion - [getLastModified()]: " + fecha);
            System.out.println("Tipo de Contenido [getContentType()]: " + conexion.getContentType());
            System.out.println("===========================================================");
            System.out.println("TODOS LOS CAMPOS DE CABECERA CON getHeaderFields(): ");
           
            //USAMOS UNA ESTRUCTURA Map PARA RECUPERAR CABECERAS
            Map camposcabecera = conexion.getHeaderFields();
            Iterator it = camposcabecera.entrySet().iterator();
            while (it.hasNext()) {
                  Map.Entry map = (Map.Entry) it.next();
                  System.out.println(map.getKey() + " : " + map.getValue());
            }
           
            System.out.println("============================================ ");
            System.out.println("CAMPOS 1 Y 4 DE CABECERA:");
            System.out.println("getHeaderField(l)=> "+ conexion.getHeaderField(1));
            System.out.println("getHeaderField(4)=> " + conexion.getHeaderField(4));
            System.out.println("============================================");
            System.out.println("CONTENIDO DE [url.getFile()]:"+ url.getFile());
            BufferedReader pagina = new BufferedReader(new InputStreamReader(url.openStream()));
           
            while ((cadena =pagina.readLine()) != null) {
                  System.out.println(cadena);
                 
            }//Fin de main
           
      }//Fin de Ejemplo3urlCon
}

Nota: Para recorrer una estructura Map podemos usar una estructura Iterator. Para obtener un iterador sobre el map se invoca a los métodos entrySet() e iterator(). Para mover el iterador utilizaremos el método next() y para comprobar si ha llegado al final usamos el método hasNext(). De la estructura recuperaremos los valores mediante getKey(), para la clave y getValue(), para el valor.

0 comentarios:

Publicar un comentario