Sockets en Java

Java proporciona mecanismos potentes y a la vez sencillos para construir programas para redes tales como Internet. Java aporta versatilidad, portabilidad, clases especializadas para gran número de servicios (incluidas de serie), manejo eficiente de la memoria, etc. Entre las clases que permiten la comunicación tenemos la clase URL en un nivel superior y las clases Socket y ServerSocket a un nivel más bajo.

Mediante la clase Socket incluida en el paquete java.net podemos crear conexiones de flujo, que son los que utilizan el protocolo TCP, entre dos ordenadores. El tipo de datos en la comunicación puede ser cualquiera, y por ello el protocolo TCP es usado por http, ftp, telnet, etc. Más adelante veremos un sencillo ejemplo de comunicación entre un navegador y una aplicación Java y veremos de forma básica como es el protocolo http y como interacciona un navegador con un servidor.

Los Sockets o enchufes son semejantes a conexiones telefónicas entre dos ordenadores remotos, la comunicación es continúa y finaliza cuando uno de los dos ordenadores cierra su conexión.

La clase ServerSocket es una clase incluida en java.net que sirve para atender peticiones de conexiones, lo cual es útil a la hora de crear un servidor. Como veremos más adelante, en un servidor hay un bucle infinito donde se llama al método accept de la clase ServerSocket quedando a la espera de aceptar una conexión. Cuando esta conexión se produce esta clase devuelve un objeto de tipo socket que es el que utiliza el servidor para comunicarse con el cliente, de este socket podemos conseguir una corriente de entrada y otra de salida.

Vamos a continuación a ver un programa sencillo ejemplo de como funcionan estas clases. Para ejecutar este programa debemos tener un JDK que compile el programa y luego lo ejecute.

Para el caso de CrearCliente necesitamos un servidor como Apache instalado en nuestra máquina que tenga la dirección localhost (127.0.0.1) o cualquier dirección de Internet a la que tengamos acceso y que sirva páginas html.

Para el caso de CrearServidor necesitamos un navegador en el cual visualizaremos lo que nos devuelve el servidor.

Método CrearCliente.-

En el método CrearCliente creamos un socket que va a conectar con una dirección de Internet local (127.0.0.1) y con index.html a través del puerto 80. A el socket se le especifican estos parámetros en el constructor.

Una vez realizada la conexión obtenemos un DataOutputStream del socket con getOutputStream y escribimos nuestra petición que en nuestro caso es igual a la que realiza el Internet Explorer. En esa corriente de salida escribimos nuestros datos. Después obtenemos un DataInputStream con getInputStream y leemos lo que nos llega que puede ser el texto de una página html. Por último cerramos la conexión con close una vez que no hay más datos que leer.

Podemos ver que la creación de un Socket es sencilla y que leer y escribir de un socket es como leer y escribir de un archivo.

Método CrearServidor

En este método vamos a crear un servidor sencillo que va atender los datos de un navegador tal como Internet Explorer. Este servidor va a servir por la dirección 127.0.0.1 que es la de localhost, y por el puerto 80. Estas dos condiciones se especifican al crear el ServerSocket (Ojo con la dirección especificada ya que tiene que existir en la máquina).

Una vez creado el ServerSocket se crea un bucle infinito en el cual el método accept espera hasta recibir una conexión. Este método al aceptar la conexión devuelve un Socket que es con el que vamos a realizar la conexión al cliente. Al igual que el método anterior obtenemos un DataInputStream con getInputStream del cual vamos a leer los datos desde el cliente.

Los datos recibidos diferirán según el navegador utilizado pero serán parecidos a los que se envían en el ejemplo de CrearCliente. Para conectar con el navegador una vez ejecutado el ejemplo tenemos que introducir en él “http://127.0.0.1:80/hola.html” y recibiremos de vuelta el contenido del String respuesta. Como el navegador encuentra en la página html la referencia a una imagen gif, realizará una segunda petición pidiendo dicha imagen.

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

public class Comunicacion
{
    public void CrearCliente()
    {
        Socket conexion=null;
        DataInputStream entrada=null;
        DataOutputStream salida=null;
        String cad="";
        byte datosBytes[]=new byte[256];
        int leido=0;
        String peticion="";

        try
        {
           conexion=new Socket (InetAddress.getByName ("http://localhost/index.html"), 80);
           System.out.println("Conectando");
           /*Enviamos lo que envía el navegador Internet Explorer al    pedir una página*/
           peticion="GET /index.html HTTP/1.1n";
           peticion+="Accept: */*n";
           peticion+="Accept-Language: esn";
           peticion+="Accept-Encoding: gzip, deflaten";
           peticion+="User-Agent: Mozilla/4.0 (compatible; MSIE 5.01;    Windows NT)n";
           peticion+="Host: 127.0.0.1n";
           peticion+="Connection: Keep-Alivenn";
           salida=new DataOutputStream(conexion.getOutputStream());
           salida.write(peticion.getBytes());
           //Vemos lo que nos envía el Servidor
            entrada=new DataInputStream(conexion.getInputStream());

                try
                {
                    while ((leido=entrada.read(datosBytes,0,256))!=1)

                    if (leido>0)
                       System.out.println (new String(datosBytes,0,(leido-1)));
                }
                catch (EOFException e) {}

             conexion.close();
        }
        catch (IOException e)
        {
            System.out.println(e.toString());
            System.out.println("Error al conectar");
        }
    }
 

    public void CrearServidor()
    {
        //Socket conexion;
        ServerSocket sck;
        BufferedReader datos;
        InputStream Entradadatos;
        String texto="";
        int cliente=0;
        int leido=0;

        try
        {
            //Creamos un servidor
            ServerSocket conexion=new ServerSocket(80,2,InetAddress.getByName("127.0.0.1"));
            DataInputStream entrada=null;
            DataOutputStream salida=null;
            String cad="",body="",respuesta="";
            byte  bytedata[]=new byte[256];

            while (true)
            {
                ++cliente;
                Socket conex=conexion.accept();

                entrada=new DataInputStream(conex.getInputStream());
                System.out.println("Cliente num "+Integer.toString(cliente));
                InetAddress direc=conex.getInetAddress();
                System.out.println ("Dirección de llamada"+direc.getHostAddress());
                cad="";
                leido=entrada.read(bytedata);
                if (leido>0)
                    cad=new String(bytedata,0,(leido-1));
                //Sacamos lo que hemos recibido desde el cliente
                System.out.println("Recibido desde cliente");
                System.out.println(cad);
                salida=new DataOutputStream(conex.getOutputStream());
                body+="<html>n";
                body+="<body>n";
                body+="<h1>Hola que tal!</h1>n";
                body+="<image src=’barra.gif’>n";
                body+="</body>n";
                body+="</html>n";

                if (cad.indexOf("barra.gif")>=0)
                {
                    respuesta="HTTP/1.0 200 OKn";
                    respuesta+="Date: Mon, 5 Nov 2001 23:59:59GMTn";
                    respuesta+="Content-Type: image/gifn";
                    respuesta+="Content-Length: 112nn";
                    //Hay que añadir la imagen
                    //Escribimos la respuesta al cliente
                    salida.write(respuesta.getBytes());
                    salida.flush();
                    try
                    {

                       FileInputStream imagen=new FileInputStream("barra.gif");
                        while((leido=imagen.read(bytedata,0,256))!=-1)
                            salida.write(bytedata,0,leido);
                            salida.flush();
                    }
                    catch (IOException e)
                    {

                    }
                }
                else if (cad.indexOf("hola.html")>=0)
                {
                    respuesta="HTTP/1.0 200 OKn";
                    respuesta+="Date: Mon, 5 Nov 2001 23:59:59 GMTn";

                    respuesta+="Content-Type: text/htmln";
                    respuesta+="Content-          Length:"+Integer.toString(body.length())+"nn";
                    respuesta+=body;
                    //Escribimos la respuesta al cliente
                    salida.writeBytes(respuesta);
                    salida.flush();
                }
                else
                {
                    respuesta="HTTP/1.0 404 Error no encontradon";
                    respuesta+="Date: Mon, 5 Nov 2001 23:59:59 GMTn";

                    respuesta+="Content-Type: text/htmln";
                    respuesta+="Content-          Length:"+Integer.toString( body.length())+"nn";
                    respuesta+="No se ha encontrado el documento";
                    //Escribimos la respuesta al cliente
                    salida.writeBytes(respuesta);
                    salida.flush();
                }

                //Cerramos el Socket
                conex.close();
            }

        }
        catch (IOException e)
        {
            System.out.println(e.toString());
            System.out.println("Error al conectar");
        }
    }
    public static void main(String[] args)
    {
        Comunicacion Comuc =new Comunicacion();
        Comuc.CrearServidor();
        //Comuc.CrearCliente();
        //Comuc.pruebaURL();
    }
}

Los ejemplos demuestran a pesar de su sencillez la potencia del Java y la sencillez de sus clases. El ejemplo del servidor se puede perfeccionar para que acepte varias conexiones simultáneas a través de varios procesos o para que responda diferentes formas diferentes según la información pedida, etc.

A partir del ejemplo expuesto debe ser el lector el que desarrolle los ejemplos y que vea cuales son los métodos de las clases y como se comportan en realidad. También se recomienda ver la clase URL que permite la conexión a través de diferentes protocolos (http, ftp, etc) especificando la dirección URL de un recurso.

Leave A Comment?