sockets cliete servidor

Upload: julio-nuevo

Post on 12-Oct-2015

16 views

Category:

Documents


0 download

TRANSCRIPT

  • INGENIERIA INFORMATICA

    0 Materia: Inteligencia Artificial

    Universidad Autnoma Juan Misael Saracho Facultad de Ciencias y Tecnologas

    Carrera de Ingeniera Informtica

    Tarija - Bolivia

  • INGENIERIA INFORMATICA

    1 Materia: Inteligencia Artificial

    SOCKETS CLIENTE -

    SERVIDOR

    Ral Morales Mendoza, Juan Edgar Mallea Machaca Ingeniera Informtica, Departamento de Ciencias y Tecnologas, Universidad Autnoma Juan Misael Saracho

    [email protected], [email protected]

    1. Objetivo

    El objetivo de este trabajo es dar a conocer una de las tantas aplicaciones que la Tecnologa de

    Programacin en Red ha logrado en este ltimo tiempo en el rea de la Informtica.

    Entonces lo que vamos a hacer es aprender los fundamentos de la programacin con sockets en Java

    ofrecida por el paquete java.net.

    Es decir, vamos a comprender cmo es posible utilizar las facilidades proporcionadas por los sockets

    de Java para desarrollar aplicaciones distribuidas, en las que uno o ms ordenadores intercambian

    informacin a travs de una red de comunicaciones

    2. INTRODUCCION

    El paquete java.net de la plataforma Java proporciona una clase Socket, la cual implementa una de las

    partes de la comunicacin bidireccional entre un programa Java y otro programa en la red.

    La clase Socket se sita en la parte ms alta de una implementacin dependiente de la plataforma,

    ocultando los detalles de cualquier sistema particular al programa Java. Usando la clase

    java.net.Socket en lugar de utilizar cdigo nativo de la plataforma, los programas Java pueden

    comunicarse a travs de la red de una forma totalmente independiente de la plataforma.

    De forma adicional, java.net incluye la clase ServerSocket, la cual implementa un socket el cual los

    servidores pueden utilizar para escuchar y aceptar peticiones de conexin de clientes.

    Nuestro objetivo ser conocer cmo utilizar las clases Socket y ServerSocket.

    Por otra parte, si intentamos conectar a travs de la Web, la clase URL y clases relacionadas

    (URLConnection, URLEncoder) son probablemente ms apropiadas que las clases de sockets. Pero

    de hecho, las clases URL no son ms que una conexin a un nivel ms alto a la Web y utilizan como

    parte de su implementacin interna los sockets.

  • INGENIERIA INFORMATICA

    2 Materia: Inteligencia Artificial

    3. SOCKETS

    Los sockets son un sistema de comunicacin entre procesos de diferentes mquinas de una red.

    Un socket es un punto de comunicacin por el cual un proceso puede emitir o recibir informacin.

    Los sockets han de ser capaces de utilizar el protocolo de streams TCP (Transfer Contro Protocol) y el

    de datagramas UDP (User Datagram Protocol).

    Utilizan una serie de primitivas para:

    Establecer el punto de comunicacin. Conectarse a una mquina remota en un determinado puerto que est disponible. Escuchar en l. Leer o escribir y publicar informacin en l. Desconectarse.

    3.1. USO DE SOCKETS

    Para obtener una descripcin detallada de las interfaces relacionadas con sockets en Java puede

    consultarse la documentacin que acompaa al JDK. En caso de no tener acceso a ella, a continuacin

    aparecen algunas de las operaciones presentes en estas clases (en concreto, aquellas que van a resultar

    necesarias para desarrollar la prctica). Tngase en cuenta que estas clases se encuentran en los

    paquetes java.net (para el caso de DatagramPacket, DatagramSocket, Inet-Address y Socket) y java.io

    (para las clases InputStream y Output-Stream). Por tanto, deber realizarse el import correspondiente

    para tener acceso a ellas.

  • INGENIERIA INFORMATICA

    3 Materia: Inteligencia Artificial

    3.2. CLASE DatagramPacket

    Esta clase modela un paquete a transmitir mediante sockets UDP. Las operaciones a utilizar van a ser:

    DatagramPacket( byte[ ] buf, int longitud )

    Constructor utilizado para poder recibir paquetes de la longitud especificada en el segundo argumento.

    El contenido del paquete se dejara en el vector de octetos especificado en el primer argumento una vez

    se haya podido recibir la informacin. Se utilizara para recibir la contestacin del servidor.

    DatagramPacket( byte[ ] buf, int longitud, InetAddress direction, int puerto )

    Constructor utilizado para poder enviar paquetes con la longitud especificada en el segundo argumento

    hacia el ordenador cuya direccin y puerto se han dado en los dos siguientes.

    Se utilizar para construir el mensaje a enviar al servidor.

    3.3. CLASE DatagramSocket

    Esta clase modela un socket UDP. Las operaciones a utilizar son:

    DatagramSocket()

    Construye un socket UDP y lo asocia a algn puerto libre en la mquina local. Aunque existen

    variantes para especificar un puerto y/o una mquina, no son de inters para el cliente (ver el cdigo del

    servidor, en la seccin 1.3) ya que aqu nicamente habr que especificar la direccin destino en los

    paquetes a enviar.

    void receive( DatagramPacket p )

    El hilo de ejecucin permanece bloqueado hasta que se ha recibido un paquete a travs de este socket.

    La informacin recibida se encuentra en el vector asociado al paquete pasado como nico argumento.

    void send( DatagramPacket p )

    Enva un paquete a travs del socket. El paquete debe tener asociada la direccin y el puerto del socket

    a quien va dirigido el envo.

  • INGENIERIA INFORMATICA

    4 Materia: Inteligencia Artificial

    3.4. CLASE InetAddress

    Esta clase modela la direccin IP de una mquina. Se necesita para especificar la ubicacin del

    servidor, bien sea en la mquina local o en una mquina remota. Las operaciones a utilizar son:

    static InetAddress getByName( String host )

    Dado un nombre de mquina, devuelve un objeto InetAddress con su direccin.

    static InetAddress getLocalHost()

    Devuelve un objeto InetAddress con la direccin de la mquina local.

    3.5. CLASE Socket

    Esta clase implementa un socket cliente con comunicacin TCP. Los sockets servidores para TCP estn

    modelados por la clase ServerSocket, pero esta ya no resulta necesaria para el caso del programa

    cliente. Obsrvese, adems, que la comunicacin TCP est orientada a conexin y en el programa

    servidor esta conexin se crea y se cierra para cada peticin efectuada por el cliente. Por tanto, el

    cliente deber estructurarse de igual manera.

    Las operaciones a utilizar son:

    Socket( String host, int puerto )

    Crea un socket y lo conecta a la mquina remota cuyo nombre sea host, en el puerto especificado como

    segundo argumento.

    InputStream getInputStream()

    Obtiene el InputStream a utilizar para obtener la informacin recibida en el socket.

    OutputStream getOutputStream()

    Obtiene el OutputStream a utilizar para enviar informacin por el socket.

    void close()

    Cierra el socket, cortando la conexin con el servidor.

  • INGENIERIA INFORMATICA

    5 Materia: Inteligencia Artificial

    3.6. CLASE ImputStream

    La nica operacin a utilizar en este caso es:

    int read()

    que devuelve el siguiente octeto presente en ese canal de entrada.

    Aunque existen otras operaciones para obtener informacin desde el InputStream, como el servidor

    nicamente escribe un octeto, en el cliente slo habr que leer ese octeto.

    3.7. CLASE OutputStream

    Al igual que en la clase anterior, nicamente hay que escribir un octeto en el socket, por lo que la operacin a

    utilizar es: void write( int octeto )

  • INGENIERIA INFORMATICA

    6 Materia: Inteligencia Artificial

    IMPLEMENTACIN

  • INGENIERIA INFORMATICA

    7 Materia: Inteligencia Artificial

    Clase Servidor

    import java.io.*;

    import java.net.*;

    import java.awt.*;

    import java.awt.event.*;

    import javax.swing.*;

    import sun.misc.JavaLangAccess;

    public class Servidor extends JFrame {

    private JTextField campoIntroducir;

    private JTextArea areaPantalla;

    private ObjectOutputStream salida;

    private ObjectInputStream entrada;

    private ServerSocket servidor;

    private Socket conexion;

    private int contador = 1;

    // configurar GUI

    public Servidor()

    {

    super( "Servidor" );

    Container contenedor = getContentPane();

    // crear campoIntroducir y registrar componente de escucha

    campoIntroducir = new JTextField();

    campoIntroducir.setEditable( false );

    campoIntroducir.addActionListener(

    new ActionListener() {

    // enviar mensaje al cliente

    public void actionPerformed( ActionEvent evento )

    {

    enviarDatos( evento.getActionCommand() );

    campoIntroducir.setText( "" );

    }

    }

    );

    //TITULO

    JLabel ltitulo=new JLabel("SERVIDOR");

    ltitulo.setFont(new java.awt.Font("Times New Roman", 1, 20));

    ltitulo.setForeground(new java.awt.Color(0, 0, 153));

    ltitulo.setAlignmentX(Component.CENTER_ALIGNMENT);

    JPanel panelDatos=new JPanel();

    panelDatos.setLayout(new BorderLayout());

    JLabel labelIntoducir=new JLabel("Enviar: ");

    panelDatos.add(labelIntoducir, BorderLayout.WEST);

    panelDatos.add(campoIntroducir, BorderLayout.CENTER);

    JPanel panelNorte=new JPanel();

  • INGENIERIA INFORMATICA

    8 Materia: Inteligencia Artificial

    panelNorte.setLayout(new BoxLayout(panelNorte, BoxLayout.Y_AXIS));

    //Poner Border al panel (Arriba, Izquierda, Abajo, Derecha)

    panelNorte.setBorder(BorderFactory.createEmptyBorder(20,10,10,10));

    panelNorte.add(ltitulo);

    panelNorte.add(panelDatos);

    contenedor.add(panelNorte, BorderLayout.NORTH );

    // crear areaPantalla

    areaPantalla = new JTextArea();

    JPanel panelArea=new JPanel();

    panelArea.setBorder(BorderFactory.createEmptyBorder(0,10,10,10));

    panelArea.setLayout(new BorderLayout());

    panelArea.add( new JScrollPane( areaPantalla ), BorderLayout.CENTER);

    contenedor.add(panelArea, BorderLayout.CENTER);

    setSize( 350, 500 );

    setLocation(20,50);

    setVisible( true );

    } // fin del constructor de Servidor

    // configurar y ejecutar el servidor

    public void ejecutarServidor()

    {

    // configurar servidor para que reciba conexiones; procesar las conexiones

    try {

    // Paso 1: crear un objeto ServerSocket.

    servidor = new ServerSocket( 12345, 100 );

    while ( true ) {

    try {

    esperarConexion(); // Paso 2: esperar una conexin.

    obtenerFlujos(); // Paso 3: obtener flujos de entrada y

    salida.

    procesarConexion(); // Paso 4: procesar la conexin.

    }

    // procesar excepcin EOFException cuando el cliente cierre la conexin

    catch ( EOFException excepcionEOF ) {

    System.err.println( "El servidor termin la conexin" );

    }

    finally {

    cerrarConexion(); // Paso 5: cerrar la conexin.

    ++contador;

    }

    } // fin de instruccin while

    } // fin del bloque try

    // procesar problemas con E/S

    catch ( IOException excepcionES ) {

  • INGENIERIA INFORMATICA

    9 Materia: Inteligencia Artificial

    excepcionES.printStackTrace();

    }

    } // fin del mtodo ejecutarServidor

    // esperar que la conexin llegue, despus mostrar informacin de la conexin

    private void esperarConexion() throws IOException

    {

    mostrarMensaje( "Esperando una conexin\n" );

    conexion = servidor.accept(); // permitir al servidor aceptar la conexin

    mostrarMensaje( "Conexin " + contador + " recibida de: " +

    conexion.getInetAddress().getHostName() );

    }

    // obtener flujos para enviar y recibir datos

    private void obtenerFlujos() throws IOException

    {

    // establecer flujo de salida para los objetos

    salida = new ObjectOutputStream( conexion.getOutputStream() );

    salida.flush(); // vaciar bfer de salida para enviar informacin de

    encabezado

    // establecer flujo de entrada para los objetos

    entrada = new ObjectInputStream( conexion.getInputStream() );

    mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );

    }

    // procesar la conexin con el cliente

    private void procesarConexion() throws IOException

    {

    // enviar mensaje de conexin exitosa al cliente

    String mensaje = "Conexin exitosa";

    enviarDatos( mensaje );

    // habilitar campoIntroducir para que el usuario del servidor pueda enviar

    mensajes

    establecerCampoTextoEditable( true );

    do { // procesar los mensajes enviados por el cliente

    // leer el mensaje y mostrarlo en pantalla

    try {

    mensaje = ( String ) entrada.readObject();

    mostrarMensaje( "\n" + mensaje );

    }

    // atrapar problemas que pueden ocurrir al tratar de leer del cliente

    catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {

    mostrarMensaje( "\nSe recibi un tipo de objeto desconocido" );

    }

    } while ( !mensaje.equals( "CLIENTE dice: chau" ) );

    } // fin del mtodo procesarConexion

    // cerrar flujos y socket

    private void cerrarConexion()

    {

  • INGENIERIA INFORMATICA

    10 Materia: Inteligencia Artificial

    mostrarMensaje( "\nFinalizando la conexin\n" );

    establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir

    try {

    salida.close();

    entrada.close();

    conexion.close();

    }

    catch( IOException excepcionES ) {

    excepcionES.printStackTrace();

    }

    }

    // enviar mensaje al cliente

    private void enviarDatos( String mensaje )

    {

    // enviar objeto al cliente

    try {

    salida.writeObject( "SERVIDOR dice: " + mensaje );

    salida.flush();

    mostrarMensaje( "\nSERVIDOR dice: " + mensaje );

    }

    // procesar problemas que pueden ocurrir al enviar el objeto

    catch ( IOException excepcionES ) {

    areaPantalla.append( "\nError al escribir objeto" );

    }

    }

    // mtodo utilitario que es llamado desde otros subprocesos para manipular a

    // areaPantalla en el subproceso despachador de eventos

    private void mostrarMensaje( final String mensajeAMostrar )

    {

    // mostrar mensaje del subproceso de ejecucin despachador de eventos

    SwingUtilities.invokeLater(

    new Runnable() { // clase interna para asegurar que la GUI se actualice

    apropiadamente

    public void run() // actualiza areaPantalla

    {

    areaPantalla.append( mensajeAMostrar );

    areaPantalla.setCaretPosition(

    areaPantalla.getText().length() );

    }

    } // fin de la clase interna

    ); // fin de la llamada a SwingUtilities.invokeLater

    }

    // mtodo utilitario que es llamado desde otros subprocesos para manipular a

    // campoIntroducir en el subproceso despachador de eventos

    private void establecerCampoTextoEditable( final boolean editable )

    {

    // mostrar mensaje del subproceso de ejecucin despachador de eventos

    SwingUtilities.invokeLater(

    new Runnable() { // clase interna para asegurar que la GUI se actualice

    apropiadamente

  • INGENIERIA INFORMATICA

    11 Materia: Inteligencia Artificial

    public void run() // establece la capacidad de modificar a

    campoIntroducir

    {

    campoIntroducir.setEditable( editable );

    }

    } // fin de la clase interna

    ); // fin de la llamada a SwingUtilities.invokeLater

    }

    public static void main( String args[] )

    {

    try

    {

    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

    }

    catch (Exception e)

    {

    e.printStackTrace();

    }

    Servidor aplicacion = new Servidor();

    aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    aplicacion.ejecutarServidor();

    }

    } // fin de la clase Servidor

  • INGENIERIA INFORMATICA

    12 Materia: Inteligencia Artificial

    Clase Cliente

    import java.io.*;

    import java.net.*;

    import java.awt.*;

    import java.awt.event.*;

    import javax.swing.*;

    public class Cliente extends JFrame {

    private JTextField campoIntroducir;

    private JTextArea areaPantalla;

    private ObjectOutputStream salida;

    private ObjectInputStream entrada;

    private String mensaje = "";

    private String servidorChat;

    private Socket cliente;

    // inicializar servidorChat y configurar GUI

    public Cliente( String host )

    {

    super( "Cliente" );

    servidorChat = host; // establecer el servidor al que se va a conectar este

    cliente

    Container contenedor = getContentPane();

    // crear campoIntroducir y registrar componente de escucha

    campoIntroducir = new JTextField();

    campoIntroducir.setEditable( false );

    campoIntroducir.addActionListener(

    new ActionListener() {

    // enviar mensaje al servidor

    public void actionPerformed( ActionEvent evento )

    {

    enviarDatos( evento.getActionCommand() );

    campoIntroducir.setText( "" );

    }

    }

    );

    //TITULO

    JLabel ltitulo=new JLabel("CLIENTE");

    ltitulo.setFont(new java.awt.Font("Times New Roman", 1, 20));

    ltitulo.setForeground(new java.awt.Color(0, 0, 153));

    ltitulo.setAlignmentX(Component.CENTER_ALIGNMENT);

    JPanel panelDatos=new JPanel();

    panelDatos.setLayout(new BorderLayout());

    JLabel labelIntoducir=new JLabel("Enviar: ");

    panelDatos.add(labelIntoducir, BorderLayout.WEST);

    panelDatos.add(campoIntroducir, BorderLayout.CENTER);

  • INGENIERIA INFORMATICA

    13 Materia: Inteligencia Artificial

    JPanel panelNorte=new JPanel();

    panelNorte.setLayout(new BoxLayout(panelNorte, BoxLayout.Y_AXIS));

    //Poner Border al panel (Arriba, Izquierda, Abajo, Derecha)

    panelNorte.setBorder(BorderFactory.createEmptyBorder(20,10,10,10));

    panelNorte.add(ltitulo);

    panelNorte.add(panelDatos);

    contenedor.add(panelNorte, BorderLayout.NORTH );

    // crear areaPantalla

    areaPantalla = new JTextArea();

    JPanel panelArea=new JPanel();

    panelArea.setBorder(BorderFactory.createEmptyBorder(0,10,10,10));

    panelArea.setLayout(new BorderLayout());

    panelArea.add( new JScrollPane( areaPantalla ), BorderLayout.CENTER);

    contenedor.add(panelArea, BorderLayout.CENTER);

    setSize( 350, 500 );

    setLocation(380,50);

    setVisible( true );

    } // fin del constructor de Cliente

    // conectarse al servidor y procesar mensajes del servidor

    private void ejecutarCliente()

    {

    // conectarse al servidor, obtener flujos, procesar la conexin

    try {

    conectarAServidor(); // Paso 1: crear un socket para realizar la conexin

    obtenerFlujos(); // Paso 2: obtener los flujos de entrada y salida

    procesarConexion(); // Paso 3: procesar la conexin

    }

    // el servidor cerr la conexin

    catch ( EOFException excepcionEOF ) {

    System.err.println( "El cliente termino la conexin" );

    }

    // procesar los problemas que pueden ocurrir al comunicarse con el servidor

    catch ( IOException excepcionES ) {

    excepcionES.printStackTrace();

    }

    finally {

    cerrarConexion(); // Paso 4: cerrar la conexin

    }

    } // fin del mtodo ejecutarCliente

    // conectarse al servidor

    private void conectarAServidor() throws IOException

    {

    mostrarMensaje( "Intentando realizar conexin\n" );

    // crear Socket para realizar la conexin con el servidor

  • INGENIERIA INFORMATICA

    14 Materia: Inteligencia Artificial

    cliente = new Socket( InetAddress.getByName( servidorChat ), 12345 );

    // mostrar la informacin de la conexin

    mostrarMensaje( "Conectado a: " +

    cliente.getInetAddress().getHostName() );

    }

    // obtener flujos para enviar y recibir datos

    private void obtenerFlujos() throws IOException

    {

    // establecer flujo de salida para los objetos

    salida = new ObjectOutputStream( cliente.getOutputStream() );

    salida.flush(); // vacar bfer de salida para enviar informacin de

    encabezado

    // establecer flujo de entrada para los objetos

    entrada = new ObjectInputStream( cliente.getInputStream() );

    mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );

    }

    // procesar la conexin con el servidor

    private void procesarConexion() throws IOException

    {

    // habilitar campoIntroducir para que el usuario del cliente pueda enviar

    mensajes

    establecerCampoTextoEditable( true );

    do { // procesar mensajes enviados del servidor

    // leer mensaje y mostrarlo en pantalla

    try {

    mensaje = ( String ) entrada.readObject();

    mostrarMensaje( "\n" + mensaje );

    }

    // atrapar los problemas que pueden ocurrir al leer del servidor

    catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {

    mostrarMensaje( "\nSe recibi un objeto de tipo desconocido" );

    }

    } while ( !mensaje.equals( "SERVIDOR>>> TERMINAR" ) );

    } // fin del mtodo procesarConexion

    // cerrar flujos y socket

    private void cerrarConexion()

    {

    mostrarMensaje( "\nCerrando conexin" );

    establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir

    try {

    salida.close();

    entrada.close();

    cliente.close();

    }

    catch( IOException excepcionES ) {

    excepcionES.printStackTrace();

    }

  • INGENIERIA INFORMATICA

    15 Materia: Inteligencia Artificial

    try{

    Thread.sleep(2000);

    }catch (Exception e) {}

    System.exit(0);

    }

    // enviar mensaje al servidor

    private void enviarDatos( String mensaje )

    {

    // enviar objeto al servidor

    try {

    salida.writeObject( "CLIENTE dice: " + mensaje );

    salida.flush();

    mostrarMensaje( "\nCLIENTE dice: " + mensaje );

    }

    // procesar los problemas que pueden ocurrir al enviar el objeto

    catch ( IOException excepcionES ) {

    areaPantalla.append( "\nError al escribir el objeto" );

    }

    }

    // mtodo utilitario que es llamado desde otros subprocesos para manipular a

    // areaPantalla en el subproceso despachador de eventos

    private void mostrarMensaje( final String mensajeAMostrar )

    {

    // mostrar mensaje del subproceso de ejecucin de la GUI

    SwingUtilities.invokeLater(

    new Runnable() { // clase interna para asegurar que la GUI se actualice

    apropiadamente

    public void run() // actualiza areaPantalla

    {

    areaPantalla.append( mensajeAMostrar );

    areaPantalla.setCaretPosition(

    areaPantalla.getText().length() );

    }

    } // fin de la clase interna

    ); // fin de la llamada a SwingUtilities.invokeLater

    }

    // mtodo utilitario que es llamado desde otros subprocesos para manipular a

    // campoIntroducir en el subproceso despachador de eventos

    private void establecerCampoTextoEditable( final boolean editable )

    {

    // mostrar mensaje del subproceso de ejecucin de la GUI

    SwingUtilities.invokeLater(

    new Runnable() { // clase interna para asegurar que la GUI se actualice

    apropiadamente

    public void run() // establece la capacidad de modificar

    campoIntroducir

    {

    campoIntroducir.setEditable( editable );

    }

    } // fin de la clase interna

  • INGENIERIA INFORMATICA

    16 Materia: Inteligencia Artificial

    ); // fin de la llamada a SwingUtilities.invokeLater

    }

    public static void main( String args[] )

    {

    try

    {

    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

    }

    catch (Exception e)

    {

    e.printStackTrace();

    }

    Cliente aplicacion;

    if ( args.length == 0 )

    aplicacion = new Cliente( "127.0.0.1" );

    else

    aplicacion = new Cliente( args[ 0 ] );

    aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    aplicacion.ejecutarCliente();

    }

    } // fin de la clase Cliente