logbitup.gif (360 bytes)

 Curso JAVA 
 Unidad 8: "Red"
 

logbitdn.gif (787 bytes)

  www.bit.es - Calendario de cursos - Solicitud de información

Curso Java
Curso Analista Programador entorno Java

Objetivos de la Unidad:


1.- Introducción

2.- Micro navegador Web (pequeño cliente HTTP)
 

   // Pincha.java (HTTP 1.1)

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

   public class Pincha
      
{
     public static void main(String args[]) throws Exception
     {
       Socket s = new Socket("www.bit.es", 80);
       InputStream in = s.getInputStream();
          
   DataOutputStream dout = new DataOutputStream(s.getOutputStream());
       dout.writeBytes("GET / HTTP/1.1\r\n");
       dout.writeBytes("Host: www.bit.es\r\n");
       
              dout.writeBytes("\r\n");

       int c;
       while ((c = in.read()) != -1)
       {
         System.out.print((char) c);
       }

     }
      
}

// Pincha.java

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

public class Pincha
{
 public static void main(String args[]) throws Exception
 {
   Socket s = new Socket("50.0.0.1", 80);
   InputStream in = s.getInputStream();
   DataOutputStream dout = new DataOutputStream(s.getOutputStream());
   dout.writeBytes("GET http://www.yahoo.com HTTP/1.0\r\n\r\n");

   int c;
   while ((c = in.read()) != -1)
   {
     System.out.print((char) c);
   }

 }
}


La librería estándar ofrece clases para manejar conexiones HTTP. Una nueva versión de Pincha podría ser la siguiente:


// Pincha.java

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

public class Pincha
{
  public static void main(String args[]) throws Exception
  {
    URL url = new URL("http://www.bit.es");
    URLConnection conn = url.openConnection();
    InputStream in = conn.getInputStream();

    int c;
    while ((c = in.read()) != -1)
    {
      System.out.print((char) c);
    }

  }
}


3.- PicoWeb server
 

// PicoWeb.java
// Este ejemplo puede no funcionar bien según la versión del navegador debido a que no leemos nada de
// lo que nos envía. Este problema se resuelve en el ejemplo siguiente MicroWeb


import java.io.*;

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

public class PicoWeb
{
 public static void main(String args[]) throws Exception
 {
  ServerSocket acceptSocket = new ServerSocket(80);
  System.out.println("PicoWeb esperando por el port 80...\r\n");
  while(true)
  {
    // se queda esperando hasta recibir un impacto
    Socket s=acceptSocket.accept();

    OutputStream output= s.getOutputStream();

    DataOutputStream d = new DataOutputStream (output);

    d.writeBytes("HTTP/1.0 200 OK\r\n\r\n");
    d.writeBytes("<html>\r\n");
    d.writeBytes("<body bgcolor=\"#FFFFFF\">\r\n");
    d.writeBytes("<h2>Hola</h2><br>\r\n");
    d.writeBytes("</body>\r\n");
    d.writeBytes("</html>\r\n");

    System.out.println("Impacto de " + s.getInetAddress());
    s.close();
  }
 }
}

4.- MicroWeb server  
 


Podemos visualizar cómo pueden llegar parámetros desde un navegador hasta un servidor. Para ello utilizaremos la siguiente página cuyo fichero denominaremos form.html y estando arrancado MicroWeb rellenaremos los campos y pulsaremos "Enviar":

<html>
<body bgcolor="#FFFFFF">
<h3>Formulario de prueba</h3>
<form action="http://localhost:8080">
  Nombre: <input type="TEXT" name="NOM"><br>  
  Tel&eacute;fono: <input type="TEXT" name="TEL"><br>

  <input type="SUBMIT" value="Enviar">
</form>
<h3>Ejemplo de envío de par&aacute;metros mediante un link</h3>
<a href="http://localhost:8080?NOM=abc&TEL=123">Link que env&iacute;a par&aacute;metros</h3>
</body>
</html>

5.- MiniWeb server (Pequeño servidor HTTP)  

6.- Pequeño cliente de correo. Envío de mensajes por SMTP

Para la especificación del protocolo ver la Unidad13
 
 

import java.io.*; 
import java.net.*; 
public class EnviarMail 
{ 
  private String servidorCorreoSaliente = "nt";

  public EnviarMail () throws UnknownHostException 
  { 
    System.out.println("Servidor de correo = " + servidorCorreoSaliente); 
    System.out.println("Nodo local = " + InetAddress.getLocalHost()); 
  } 
  public void send (String from, String to, String subject, String texto) throws IOException 
  { 
    checkEmailAddress(from); 
    checkEmailAddress(to);
    Socket sock = new Socket(servidorCorreoSaliente, 25);
    DataInputStream in = new DataInputStream(sock.getInputStream()); 
    // los convierte en utilizables 
    DataOutputStream out = new DataOutputStream(sock.getOutputStream());

    String initialID = in.readLine(); System.out.println(initialID);
    out.writeBytes("HELO " + InetAddress.getLocalHost() + "\r\n"); 
    System.out.println("HELO " + InetAddress.getLocalHost());
    String welcome = in.readLine(); System.out.println(welcome);
    out.writeBytes("MAIL FROM:<" + from + ">" + "\r\n"); 
    System.out.println("MAIL FROM:<" + from + ">");
    String senderOK = in.readLine(); System.out.println(senderOK);
    out.writeBytes("RCPT TO:<" + to + ">" + "\r\n"); 
    System.out.println("RCPT TO:<" + to + ">");
    String recipientOK = in.readLine(); 
    System.out.println(recipientOK);
    out.writeBytes("DATA" + "\r\n"); 
    System.out.println("DATA"); 
    String dataOK = in.readLine(); 
    System.out.println(dataOK);
    out.writeBytes("From: " + from + "\r\n"); 
    System.out.println("From: " + from); 
    out.writeBytes("To: " + to + "\r\n"); 
    System.out.println("To: " + to); 
    out.writeBytes("Subject: " + subject + "\r\n\r\n"); 
    System.out.println("Subject: " + subject + "\n");
    out.writeBytes(texto + "\r\n"); 
    System.out.println(texto);
    out.writeBytes("." + "\r\n"); 
    System.out.println(".");
    String acceptedOK = in.readLine(); 
    System.out.println(acceptedOK);
    out.writeBytes("QUIT" + "\r\n"); 
    System.out.println("QUIT"); 
    String quitOK = in.readLine(); 
    System.out.println(quitOK); 
  }
  public void checkEmailAddress(String email) 
  { 
    if (email == null || email.indexOf('@') < 0) 
    {
      System.out.println("Direccion incorrecta de correo '" + email + "'"); 
      System.exit(0); 
    } 
  }
  public static void main(String[] args) throws IOException, UnknownHostException 
  { 
    if (args.length != 4) 
    { 
      System.out.println("Uso: EnviarMail origen destino subject texto"); 
      System.exit(0); 
    }
    EnviarMail mail = new EnviarMail (); 
    mail.send(args[0], args[1], args[2], args[3]); 
    // from, to, subject, texto 
  } 
}

Actualmente se dispone de las extensiones estándar JavaMail para el envío y recepción de mensajes. Para trabajar con JavaMail hacen falta los paquetes de JavaMail y Java Activation (mail.jar y activation.jar). Se adjunta Emailer.java, que puede ser utilizada para enviar mensajes con ficheros adjuntos.

7.- Pequeño cliente FTP  
 

import sun.net.ftp.*;
import sun.net.*;
import java.net.*;
import java.io.*;

public class TryFtp
{
   static FtpClient ftp;
   public static void main(String args[]) Exception
   {
      StringBuffer buf = new StringBuffer();
      int ch;
      ftp = new FtpClient(args[0]);
      ftp.login("ftp","tdr20@cus.cam.ac.uk");
      ftp.ascii();
      TelnetInputStream t = ftp.list();

      while((ch = t.read()) >= 0)
         buf.append((char)ch);

      t.close();
      System.out.println(buf.toString());
      System.out.println("\nFichero a bajar:\n");
      buf.setLength(0);

      while((ch = System.in.read()) != '\n')
         buf.append((char)ch);

      t = ftp.get(buf.toString());
      buf.setLength(0);

      while((ch = t.read()) >= 0)
         buf.append((char)ch);

      t.close();
      System.out.println(buf.toString());
   }
}


 

8.- Pequeño servidor FTP  
 

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

/**
  Comandos tenidos en cuenta:
  CDUP, CWD, DELE, LIST, NLST, PASS, PORT, PWD, QUIT, RETR, STOR, SYS, TYPE, USER
*/
public class MiniFtp extends Thread
{
  private Socket incoming;
  private int counter;
  private static String r;

  public static void main(String[] args)
  {
    File f = new File(".");
    r = f.getAbsolutePath();

    int i = 1;

    try
    {
     ServerSocket s = new ServerSocket(21);
     System.out.println("Tiny FTP server arrancado ...\n");

     for(;;)
     {
       Socket incoming = s.accept();
       new MiniFtp(incoming, i).start();
       i++;
     }
   }
   catch(Exception e)
   {
     e.printStackTrace();
   }

}


public MiniFtp(Socket income, int c)
{
  incoming = income; counter = c;
}


public void run()
{
  int lng, lng1, lng2, i, ip1, ip2, ip = 1 ,h1;
  String a1, a2, di, str1, user = "", host, dir;
  System.out.println(r);
  dir = r;
  InetAddress inet;
  InetAddress localip;

  try
  {
    inet = incoming.getInetAddress();
    localip = inet.getLocalHost();
    host = inet.toString();
    h1 = host.indexOf("/");
    host = host.substring(h1 + 1);

    // System.out.println(host);
    BufferedReader in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
    PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
    out.println("220 MyFtp server ready.\r");

    boolean quit = false;
    while(!quit)
    {
      a1 = "";
      a2 = "";

      String strOrig = in.readLine();
      String str = "";
      str = strOrig;

      System.out.println(str);


      if(str.startsWith("CDUP"))
      {
        int n = dir.lastIndexOf("/");
        dir = dir.substring(0,n);
        out.println("250 CWD command succesful");
      }
      else if(str.startsWith("CWD"))
      {
        str1 = str.substring(3);
        dir = dir + "/" + str1.trim();
        out.println("250 CWD command succesful");
      }
      else if(str.startsWith("DELE"))
      {
        str = str.substring(4);
        str = str.trim();
        File f = new File(dir,str);
        boolean del = f.delete();
        out.println("250 delete command successful");
      }
      else if(str.startsWith("LIST") || str.startsWith("NLST"))
      {
        try
        {
          out.println("150 ASCII data");

          Socket t = new Socket(host,ip);
          PrintWriter out2 = new PrintWriter(t.getOutputStream(), true);

          File f = new File(dir);
          String[] a = new String[10];
          String d, e;
          int i1, j1;
          a = f.list();
          j1 = a.length;
          d = f.getName();

          for(i1 = 0; i1 < j1; i1++)
          {
            di = "";
            if(str.startsWith("LIST"))
            {
              if( a[i1].indexOf(".") == -1)
              {
                di = "d ";
              }
              else
              {
                di = "- ";
              }
            }
            out2.println(di+a[i1]);
          }
          t.close();
          out.println("226 transfer complete");
        }
        catch(IOException e)
        {
          e.printStackTrace();
        }
      }
      else if(str.startsWith("PASS"))
      {
        out.println("230 User " + user + " logged in.");
      }
      else if(str.startsWith("PORT"))
      {
        out.println("200 PORT command successful");
        lng = str.length() - 1;
        lng2 = str.lastIndexOf(",");
        lng1 = str.lastIndexOf("," , lng2-1);

        for(i = lng1+1; i < lng2; i++)
        {
          a1 = a1 + str.charAt(i);}

          for(i = lng2+1; i <= lng; i++)
          {
            a2 = a2 + str.charAt(i);
          }

          ip1 = Integer.parseInt(a1);
          ip2 =Integer.parseInt(a2);
          ip = ip1 * 16 *16 + ip2;
        }
        else if(str.startsWith("PWD"))
        {
          out.println("257 \"" + dir + "\" is current directory");
        }
        else if(str.startsWith("QUIT"))
        {
          out.println("BYE");
          quit = true;
        }
        else if(str.startsWith("RETR"))
        {
          str = str.substring(4);
          str = str.trim();
          System.out.println(str);
          System.out.println(dir);

          File f = new File(dir + "/" + str);
          if (f.exists())
          {
            out.println("150 Binary data connection");
            RandomAccessFile outFile = new RandomAccessFile(f, "r");
            Socket t = new Socket(host, ip);
            OutputStream out2 = t.getOutputStream();

            byte[] bb = new byte[1024];
            int amount;

            try
            {
              while((amount = outFile.read(bb)) != -1)
              {
                out2.write(bb, 0, amount);
              }

              out2.close();
              out.println("226 transfer complete");
              outFile.close();
              t.close();
            }
            catch(IOException e)
            {
              e.printStackTrace();
            }
          }
          else
          {
            out.println("500 Can't open " + str + ": No such file or directory");
          }
        }
        else if(str.startsWith("STOR"))
        {
          out.println("150 Binary data connection");
          str = str.substring(4);
          str = str.trim();
          System.out.println(str);
          System.out.println(dir);
          RandomAccessFile inFile = new
          RandomAccessFile(dir + "/" + str, "rw");
          Socket t = new Socket(host,ip);
          InputStream in2 = t.getInputStream();

          byte bb[] = new byte[1024];
          int amount;
          try
          {
            while((amount = in2.read(bb)) != -1)
            {
              inFile.write(bb, 0, amount);
            }

            in2.close();
            out.println("226 transfer complete");
            inFile.close();
            t.close();
          }
          catch(IOException e)
          {
            e.printStackTrace();
          }
        }
        else if(str.startsWith("SYS"))
        {
          out.println("500 SYS not understood");
        }
        else if(str.startsWith("TYPE"))
        {
          out.println("200 type set");
        }
        else if(str.startsWith("USER"))
        {
          user = str.substring(4);
          user = user.trim();
          out.println("331 Password");
        }
        else
        {
          out.println("500 " + str + " not understood");
        }
      }
      incoming.close();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}
 

Una versión Open Source basada en este servidor FTP pero mucho más completa puede obtenerse en http://www.theorem.com/java/Free.htm#FTPServer
Comentario final: El JDK incluye en los paquetes de sun clases como FtpClient, SmtpClient, HttpClient, NntpClient, TelnetInputStream entre otras.

 

8.- RMI

La idea es poder referenciar un objeto remoto (una instancia de una clase) como si estuviera en local y poder utilizar sus métodos con toda transparencia. El concepto está basado en el design pattern denominado proxy, simplifica enormemente todo lo relativo a servicios remotos siendo muy idóneo para la comunicación applets/servlets. Puede considerarse una característica de gran potencia.

Más sobre patrones de diseño: Generales: http://webs.teleprogramadores.com/patrones  y J2EE: http://java.sun.com/blueprints (patterns)

/**********************************
* ObjRemotoInterface.java
**********************************/
import java.rmi.*;

public interface ObjRemotoInterface extends Remote
{
  String getHola() throws RemoteException;
}
 


/**********************************
* ObjRemoto.java
**********************************/
import java.rmi.*;
import java.rmi.server.*;


public class ObjRemoto extends UnicastRemoteObject implements ObjRemotoInterface
{
  public ObjRemoto() throws RemoteException {}
  
  public String getHola() throws RemoteException
  {
    System.out.println("Enviando Hola");
    return "Hola";
  }
}


/**********************************
* AplicacionLocal.java
**********************************/

//Nota relativa al nombre de la clase y del interface para los objetos remotos:
//
// Los nombres escogidos ObjRemoto y ObjRemotoInterface han sido escogidos para facilitar
// la comprensión del ejemplo inicial.
// La nomenclatura definitiva para un caso real pasaría a ser respectivamente a
// ObjRemotoImpl y ObjRemoto


import java.rmi.*;

public class AplicacionLocal
{
  public static void main(String[] args) throws Exception
  {
    System.setSecurityManager(new RMISecurityManager());
    
    ObjRemotoInterface obj =
     (ObjRemotoInterface) Naming.lookup("rmi://192.0.0.1:6789/prueba.ObjRemoto");
    
    String s = obj.getHola();
    System.out.println(s);
  }
}

/**********************************
* AplicacionRemota.java
**********************************/
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;

public class AplicacionRemota
{
  public static void main(String[] args) throws Exception
  {
    System.setSecurityManager(new RMISecurityManager());
    LocateRegistry.createRegistry(6789);
    ObjRemoto obj = new ObjRemoto();
    Naming.rebind("//:6789/prueba.ObjRemoto", obj);
  }
}

 

Para ejecutar en Java 2 hay que indicar en el comando de ejecución el fichero de políticas de seguridad a aplicar:

java -Djava.security.policy=c:\cursojava\java.policy Aplicacion<local y/o remota>

donde el java.policy más permisivo es:

grant
{
    permission java.security.AllPermission;
};


Se adjunta a continuación un ejemplo completo sobre un convertidor de monedas, ejercicio típico de EJBs adaptado a RMI. Obsérvese la nomenclatura de los ficheros: Convertidor.java (equivalente a ObjRemotoInterface) para el interface y ConvertidorImpl.java para la implementación (equivalente a ObjRemoto).

Descargar cliente_rmi.zip

Descargar servidor_rmi.zip


9.- Comunicaciones sobre Sockets encriptados

En relación a SSL (Secure Sockets Layer) la página de referencia es http://wp.netscape.com/eng/ssl3 y una introducción interesante en http://www.homeport.org/~adam/ssl.html. Y en general en cuanto a criptografía una buena página de referencia es http://www.cs.auckland.ac.nz/~pgut001/links.html


Unidad anterior - Unidad siguiente