Java

POO (Programación Orientada a Objetos). Clases. Objetos. Herencia. Multihilo. Multithread. Arquitectura Cliente # Servidor

  • Enviado por: Dfgdavid
  • Idioma: castellano
  • País: España España
  • 28 páginas
publicidad

CÓDIGO DEL CLIENTE

/*

CODIGO DEL CLIENTE

NOMBRE DE LA CLASE Client.java

*/

//LISTA DE PAQUETES A IMPORTAR

import java.io.*;

import java.net.*;

import java.util.*;

import javax.swing.*;

import java.awt.*;

//ESTA CLASE PERMITE CREAR EL INTERFAZ DEL CHAT HACIA EL USUARIO Y CREAR UNA HEBRA O HIJO DENTRO

//DE LA MISMA QUE SE ENCARGA DE LA COMUNICACION CON EL SERVIDOR

public class Client extends javax.swing.JFrame

{

//CONSTRUCTOR DE LA CLASE "Client"

public Client()

{

nombreCorrecto=false; //PARA CONTROLAR SI EL USUARIO SE HA DADO DE ALTA

initComponents(); //INICIALIZA EL FORMULARIO

/*PARA QUE LA VENTANA SE AJUSTE A LA MEDIDA ELEGIDA Y AL DISEÑO DE SUS SUBCOMPONENTES.

SI LA VENTANA Y/O SUS SUBCOMPONENTES NO ESTAN TODAVIA DESPLEGADOS, AMBOS SON DESPLEGADOS ANTES

DE CALCULAR EL TAMAÑO ELEGIDO. LA VENTANA SERA CONFIRMADA DESPUES DE QUE EL TAMAÑO ELEGIDO ES

CALCULADO*/

pack();

//CREA UN HIJO O HEBRA PARA GESTIONAR EL PASO DE MENSAJES CON EL SERVIDOR

hebra=new objetoCliente(this);

//LANZA LA EJECUCION DE LA HEBRA

hebra.start();

}//FIN CONSTRUCTOR Client

//ESTE METODO ES LLAMADO DESDE DENTRO DEL CONSTRUCTOR PARA INICIALIZAR EL FORMULARIO

private void initComponents()

{

// timer1 = new org.netbeans.examples.lib.timerbean.Timer();

// timer2 = new org.netbeans.examples.lib.timerbean.Timer();

//DECLARACION DE OBJETOS

//ESTE OBJETO REPRESENTA UN PANEL O MARCO DONDE PODEMOS INSERTAR OTROS OBJETOS, INCLUSO NUEVOS

//"JPanel"

jPanel1 = new javax.swing.JPanel();

jPanel10 = new javax.swing.JPanel();

//(ESTE OBJETO REPRESENTA UNA ETIQUETA "Usuario")

jLabel2 = new javax.swing.JLabel();

//ESTE OBJETO REPRESENTA UNA CAJA DE EDICION DONDE PODEMOS ESCRIBIR TEXTO (En esta concretamente

//introduciremos el nombre de usuario al iniciar la ejecucion del programa y posteriormente sera

//deshabilitada)

nombreUsuario = new javax.swing.JTextField();

jPanel11 = new javax.swing.JPanel();

jPanel12 = new javax.swing.JPanel();

jPanel17 = new javax.swing.JPanel();

jPanel18 = new javax.swing.JPanel();

//ESTE OBJETO REPRESENTA UN BOTON AL QUE NORMALMENTE SE LE ASOCIA UN EVENTO AL SER PULSADO (Este

//(boton utilizado para terminar la ejecución del programa "SALIR")

jButton1 = new javax.swing.JButton();

//(boton utilizado para realizar un privado "PRIVADO")

jButton2 = new javax.swing.JButton();

jPanel19 = new javax.swing.JPanel();

jPanel2 = new javax.swing.JPanel();

jPanel6 = new javax.swing.JPanel();

//("Mensajes")

jLabel1 = new javax.swing.JLabel();

jPanel7 = new javax.swing.JPanel();

//ESTE OBJETO REPRESENTA UN MARCO NORMALMENTE USADO PARA INSERTAR OBJETOS EN EL COMO POR EJEMPLO

//UN "JList"

jScrollPane2 = new javax.swing.JScrollPane();

//REPRESENTA UNA VENTANA DONDE SE PUEDE AÑADIR TEXTO MEDIANTE EL METODO CORRESPONDIENTE (En esta

//(concretamente apareceran los mensajes enviados y recibidos al servidor)

messages = new javax.swing.JList();

jPanel8 = new javax.swing.JPanel();

//(En esta concretamente introduciremos los mensajes a enviar al servidor)

text = new javax.swing.JTextField();

jPanel13 = new javax.swing.JPanel();

//PAG 8-7

jPanel15 = new javax.swing.JPanel();

jPanel16 = new javax.swing.JPanel();

jPanel5 = new javax.swing.JPanel();

jScrollPane1 = new javax.swing.JScrollPane();

//(Almacena una lista de los usuarios activos en el sistema)

users = new javax.swing.JList();

jPanel9 = new javax.swing.JPanel();

//(Este boton permite enviar mensajes al servidor "ENVIAR")

send = new javax.swing.JButton();

jPanel3 = new javax.swing.JPanel();

//("Lista de usuarios")

jLabel3 = new javax.swing.JLabel();

jPanel4 = new javax.swing.JPanel();

jPanel14 = new javax.swing.JPanel();

jPanel20 = new javax.swing.JPanel();

jPanel21 = new javax.swing.JPanel();

//ASIGNACION DE FONDOS Y BORDES DE LOS OBJETOS

jPanel1.setBackground( new java.awt.Color(255,175,175) );

jPanel2.setBackground( new java.awt.Color(255,175,175) );

jPanel3.setBackground( new java.awt.Color(255,175,175) );

jPanel4.setBackground( new java.awt.Color(255,175,175) );

jPanel5.setBackground( new java.awt.Color(255,175,175) );

jPanel6.setBackground( new java.awt.Color(255,175,175) );

jPanel7.setBackground( new java.awt.Color(255,175,175) );

jPanel8.setBackground( new java.awt.Color(255,175,175) );

jPanel9.setBackground( new java.awt.Color(255,175,175) );

jPanel10.setBackground( new java.awt.Color(255,175,175) );

jPanel11.setBackground( new java.awt.Color(255,175,175) );

jPanel12.setBackground( new java.awt.Color(255,175,175) );

jPanel13.setBackground( new java.awt.Color(255,175,175) );

jPanel14.setBackground( new java.awt.Color(255,175,175) );

jPanel15.setBackground( new java.awt.Color(255,175,175) );

jPanel16.setBackground( new java.awt.Color(255,175,175) );

jPanel17.setBackground( new java.awt.Color(255,175,175) );

jPanel18.setBackground( new java.awt.Color(255,175,175) );

jPanel19.setBackground( new java.awt.Color(255,175,175) );

jPanel20.setBackground( new java.awt.Color(255,175,175) );

jPanel21.setBackground( new java.awt.Color(255,175,175) );

jButton1.setBackground( new java.awt.Color(255,255,0) );

jButton2.setBackground( new java.awt.Color(255,255,0) );

send.setBackground( new java.awt.Color(255,255,0) );

jLabel1.setBackground( new java.awt.Color(255,175,175) );

jLabel2.setBackground( new java.awt.Color(255,175,175) );

jLabel3.setBackground( new java.awt.Color(255,175,175) );

jScrollPane1.setBackground( new java.awt.Color(255,175,175) );

jScrollPane2.setBackground( new java.awt.Color(255,175,175) );

messages.setBorder( new javax.swing.border.EtchedBorder( javax.swing.border.EtchedBorder.LOWERED, new java.awt.Color(0,255,255), new java.awt.Color(0,255,0) ) );

users.setBorder( new javax.swing.border.EtchedBorder( javax.swing.border.EtchedBorder.LOWERED, new java.awt.Color(0,255,255), new java.awt.Color(0,255,0) ) );

nombreUsuario.setBorder( new javax.swing.border.EtchedBorder( javax.swing.border.EtchedBorder.LOWERED, new java.awt.Color(0,0,255), new java.awt.Color(0,255,255) ) );

text.setBorder( new javax.swing.border.EtchedBorder( javax.swing.border.EtchedBorder.LOWERED, new java.awt.Color(0,0,255), new java.awt.Color(0,255,255) ) );

//¿DESHABILITA EL PODER MAXIMIZAR LA VENTANA O MODIFICAR SU TAMAÑO, SOLO PODEMOS MINIMIZARLA?

setResizable(false);

//ESPECIFICAMOS UN EVENTO QUE SE DEBE PRODUCIR CUANDO CAMBIE EL ESTADO DE LA VENTANA DEL

//FORMULARIO, CONCRETAMENTE EN ESTE CASO CUANDO LA VENTANA SE CIERRE SE LLAMA AL METODO

//"exitForm" CUYA IMPLEMENTACION SE ENCUENTRA MAS ABAJO

addWindowListener (new java.awt.event.WindowAdapter()

{

public void windowClosing(java.awt.event.WindowEvent evt)

{

exitForm(evt);

}

}

);

//DIVIDIMOS EL PANEL EN 5 PARTES (CENTRO, NORTE, SUR, ESTE Y OESTE)

jPanel1.setLayout (new java.awt.BorderLayout ());

//ESTABLECEMOS UN TAMAÑO PARA EL PANEL

jPanel1.setPreferredSize (new java.awt.Dimension (200, 100));

//PARA QUE NO NOS MODIFIQUE EL TAMAÑO ESTABLECIDO

jPanel1.setMaximumSize (jPanel1.getPreferredSize ());

jPanel1.setMinimumSize (jPanel1.getPreferredSize ());

//PERMITE INTRODUCIR CAJAS DENTRO DE UN PANEL Y AGRUPAR EN ESTAS VARIOS COMPONENTES

jPanel10.setLayout (new javax.swing.BoxLayout (jPanel10,0));

jPanel10.setMaximumSize (jPanel10.getPreferredSize ());

jPanel10.setMinimumSize (jPanel10.getPreferredSize ());

//ASIGNAMOS AL CAMPO "text" DEL "JLabel" UNA CADENA DE TEXTO

jLabel2.setText ("Usuario");

//AÑADIMOS AL jPanel10 el jLabel2

jPanel10.add (jLabel2);

nombreUsuario.setPreferredSize (new java.awt.Dimension(100, 18));

nombreUsuario.setMaximumSize (nombreUsuario.getPreferredSize ());

nombreUsuario.setMinimumSize (nombreUsuario.getPreferredSize ());

//AÑADIMOS AL jPanel10 EL JTextField DECLARADO ANTERIORMENTE IDENTIFICADO COMO "nombreUsuario"

jPanel10.add (nombreUsuario);

//AÑADIMOS EL jPanel10 EN EL CENTRO DEL jPanel1

jPanel1.add (jPanel10, java.awt.BorderLayout.CENTER);

//PAG 8-8

jPanel11.setPreferredSize (new java.awt.Dimension(400, 10));

jPanel11.setMaximumSize (jPanel11.getPreferredSize ());

jPanel11.setMinimumSize (jPanel11.getPreferredSize ());

jPanel1.add (jPanel11, java.awt.BorderLayout.NORTH);

jPanel12.setPreferredSize (new java.awt.Dimension (400, 10));

jPanel12.setMaximumSize (jPanel12.getPreferredSize ());

jPanel12.setMinimumSize (jPanel12.getPreferredSize ());

jPanel1.add (jPanel12, java.awt.BorderLayout.SOUTH);

jPanel17.setPreferredSize (new java.awt.Dimension (100, 10));

jPanel17.setMaximumSize (jPanel17.getPreferredSize ());

jPanel17.setMinimumSize (jPanel17.getPreferredSize ());

jPanel1.add (jPanel17, java.awt.BorderLayout.WEST);

jPanel18.setLayout (new java.awt.BorderLayout ());

//ASIGNAMOS AL CAMPO "text" DEL "JButton1" UNA CADENA DE TEXTO

jButton1.setText("SALIR");

//HACE LO MISMO QUE EL ANTERIOR

jButton1.setLabel("SALIR");

//ESPECIFICAMOS UN EVENTO QUE SE DEBE PRODUCIR CUANDO CAMBIE EL ESTADO DEL BOTON IDENTIFICADO

//COMO "jButton1", CONCRETAMENTE CUANDO PINCHEMOS EN EL CON EL RATON SE LLAMA AL METODO

//ESPECIFICADO CUYA IMPLEMENTACION SE ENCUENTRA MAS ABAJO

jButton1.addMouseListener (new java.awt.event.MouseAdapter ()

{

public void mouseClicked (java.awt.event.MouseEvent evt)

{

jButton1MouseClicked (evt);

}

}

);

//ASIGNAMOS AL CAMPO "text" DEL "JButton2" UNA CADENA DE TEXTO

jButton2.setText("PRIVADO");

//ESPECIFICAMOS UN EVENTO QUE SE DEBE PRODUCIR CUANDO CAMBIE EL ESTADO DEL BOTON IDENTIFICADO

//COMO "jButton2", CONCRETAMENTE CUANDO PINCHEMOS EN EL CON EL RATON SE LLAMA AL METODO

//ESPECIFICADO CUYA IMPLEMENTACION SE ENCUENTRA MAS ABAJO

jButton2.addMouseListener (new java.awt.event.MouseAdapter ()

{

public void mouseClicked (java.awt.event.MouseEvent evt)

{

jButton2MouseClicked (evt);

}

}

);

jPanel19.setPreferredSize (new java.awt.Dimension (30, 5));

jPanel19.setMaximumSize (jPanel19.getPreferredSize ());

jPanel19.setMinimumSize (jPanel19.getPreferredSize ());

jPanel18.add(jPanel19, java.awt.BorderLayout.CENTER);

jPanel20.setLayout (new java.awt.BorderLayout ());

jPanel21.setPreferredSize (new java.awt.Dimension (20, 20));

jPanel21.setMaximumSize (jPanel21.getPreferredSize ());

jPanel21.setMinimumSize (jPanel21.getPreferredSize ());

jPanel20.add (jButton1, java.awt.BorderLayout.EAST);

jPanel20.add (jPanel21, java.awt.BorderLayout.CENTER);

jPanel20.add (jButton2, java.awt.BorderLayout.WEST);

jPanel18.add(jPanel20, java.awt.BorderLayout.NORTH);

jPanel1.add(jPanel18, java.awt.BorderLayout.EAST);

//INTRODUCIMOS EN LA PARTE NORTE DE LA VENTANA O FORMULARIO PRINCIPAL EL jPanel1

getContentPane().add (jPanel1, java.awt.BorderLayout.NORTH);

//PAG 8-9

jPanel2.setLayout (new java.awt.BorderLayout ());

jLabel1.setText("Mensajes");

jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

jPanel6.add(jLabel1);

jPanel2.add (jPanel6, java.awt.BorderLayout.NORTH);

jPanel7.setPreferredSize (new java.awt.Dimension (300, 300));

jPanel7.setMaximumSize (jPanel17.getPreferredSize ());

jPanel7.setMinimumSize (jPanel17.getPreferredSize ());

jScrollPane2.setPreferredSize (jPanel7.getPreferredSize());

jScrollPane2.setMaximumSize (jPanel7.getPreferredSize ());

jScrollPane2.setMinimumSize (jPanel7.getPreferredSize ());

//ASIGNAMOS AL jScrollPane2 EL jList DECLARADO ANTERIORMENTE DE NOMBRE "messages"

jScrollPane2.setViewportView (messages);

jPanel7.add (jScrollPane2);

jPanel2.add (jPanel7, java.awt.BorderLayout.CENTER);

jPanel8.setLayout (new java.awt.BorderLayout ());

//AÑADIMOS AL jPanel8 EL JTextField DECLARADO ANTERIORMENTE DE NOMBRE "text"

jPanel8.add (text, java.awt.BorderLayout.CENTER);

jPanel2.add (jPanel8, java.awt.BorderLayout.SOUTH);

getContentPane ().add (jPanel2, java.awt.BorderLayout.CENTER);

jPanel13.setPreferredSize (new java.awt.Dimension (20, 300));

jPanel13.setMaximumSize (jPanel13.getPreferredSize ());

jPanel13.setMinimumSize (jPanel13.getPreferredSize ());

getContentPane ().add (jPanel13, java.awt.BorderLayout.WEST);

//PAG 8-10

jPanel15.setPreferredSize (new java.awt.Dimension (400, 20));

jPanel15.setMaximumSize (jPanel15.getPreferredSize ());

jPanel15.setMinimumSize (jPanel15.getPreferredSize ());

getContentPane ().add (jPanel15, java.awt.BorderLayout.SOUTH);

jPanel16.setLayout (new java.awt.BorderLayout ());

jPanel5.setPreferredSize (new java.awt.Dimension (100, 325));

jPanel5.setMaximumSize (jPanel5.getPreferredSize ());

jPanel5.setMinimumSize (jPanel5.getPreferredSize ());

jScrollPane1.setPreferredSize (new java.awt.Dimension(90,300));

jScrollPane1.setMaximumSize (jScrollPane1.getPreferredSize ());

jScrollPane1.setMinimumSize (jScrollPane1.getPreferredSize ());

users.setPreferredSize (new java.awt.Dimension(80,230));

users.setMaximumSize (users.getPreferredSize ());

users.setMinimumSize (users.getPreferredSize ());

jScrollPane1.setViewportView (users);

jPanel5.add(jScrollPane1);

jPanel16.add (jPanel5, java.awt.BorderLayout.CENTER);

//DETERMINA EL COMANDO DE ACCION PARA ESTE BOTON

send.setActionCommand ("ENVIAR");

//ASIGNAMOS AL CAMPO "Label" DEL "send" UNA CADENA DE TEXTO

send.setLabel ("ENVIAR");

//ESPECIFICAMOS UN EVENTO QUE SE DEBE PRODUCIR CUANDO CAMBIE EL ESTADO DEL BOTON IDENTIFICADO

//COMO "send", CONCRETAMENTE CUANDO PINCHEMOS EN EL CON EL RATON SE LLAMA AL METODO

//ESPECIFICADO CUYA IMPLEMENTACION SE ENCUENTRA MAS ABAJO

send.addMouseListener (new java.awt.event.MouseAdapter ()

{

public void mouseClicked (java.awt.event.MouseEvent evt)

{

SendMouseClicked(evt);

}

}

);

jPanel9.add (send);

//PAG 8-11

jPanel16.add (jPanel9, java.awt.BorderLayout.SOUTH);

jPanel3.setPreferredSize (new java.awt.Dimension (15, 220));

jPanel3.setMaximumSize (jPanel3.getPreferredSize ());

jPanel3.setMinimumSize (jPanel3.getPreferredSize ());

jPanel16.add (jPanel3, java.awt.BorderLayout.WEST);

jLabel3.setText("Lista de usuarios");

jPanel4.setPreferredSize (new java.awt.Dimension (20, 25));

jPanel4.setMaximumSize (jPanel4.getPreferredSize ());

jPanel4.setMinimumSize (jPanel4.getPreferredSize ());

jPanel4.add (jLabel3);

jPanel16.add (jPanel4, java.awt.BorderLayout.NORTH);

jPanel14.setPreferredSize (new java.awt.Dimension (15, 220));

jPanel14.setMaximumSize (jPanel14.getPreferredSize ());

jPanel14.setMinimumSize (jPanel14.getPreferredSize ());

jPanel16.add(jPanel14,java.awt.BorderLayout.EAST);

getContentPane().add(jPanel16, java.awt.BorderLayout.EAST);

}//FINAL METODO initComponents

//DECLARACION DEL EVENTO QUE SE DEBE PRODUCIR TRAS LA PULSACION DEL BOTON jButton1 (SALIR)

private void jButton1MouseClicked (java.awt.event.MouseEvent evt)

{

String texto=".s";

hebra.enviar(texto);

}//FINAL jButton1MouseClicked

//DECLARACION DEL EVENTO QUE SE DEBE PRODUCIR TRAS LA PULSACION DEL BOTON jButton2 (PRIVADO)

private void jButton2MouseClicked (java.awt.event.MouseEvent evt)

{

int posicion;

posicion=users.getSelectedIndex();

if (posicion==-1) //TEXTO A MOSTRAR SI NO HAY NINGUN USUARIO SELECCIONADO

{

text.setText(".p<usuario>@");

}

else //TEXTO HA MOSTRAR SI HAY ALGUN USUARIO SELECCIONADO

{

text.setText(".p".concat(users.getSelectedValue().toString()).concat("@"));

users.clearSelection();

}

}

//DECLARACION DEL EVENTO QUE SE DEBE PRODUCIR TRAS LA PULSACION DEL BOTON send (ENVIAR)

private void SendMouseClicked (java.awt.event.MouseEvent evt)

{

//CASO EN QUE EL USUARIO AUN NO SE HA DADO DE ALTA

if ( !nombreCorrecto)

{

String nomb=nombreUsuario.getText();

//CASO EN QUE SE HA INTRODUCIDO EL NOMBRE DEL USUARIO POR PRIMERA VEZ

if (nomb.length()>0)

{

hebra.enviar(nomb);

nombreUsuario.setEditable(false);

nombreCorrecto=true;

//CASO EN QUE EL USUARIO NO HA INTRODUCIDO NINGUN NOMBRE

}else

{//MENSAJE DE ALERTA INDICANDO QUE AUN NO SE HA ASIGNADO NOMBRE AL USUARIO

//PAG 8-12

//MUESTRA MENSAJE DE ALERTA EN TERMINAL O ENTORNO MS-DOS

System.out.println("ERROR: No tienes nombre asignado");

//MUESTRA MENSAJE DE ALERTA EN FORMULARIO O INTERFAZ DEL CLIENTE

JOptionPane mensajeError=new JOptionPane ("No ha introducido el nombre de usuario", JOptionPane.WARNING_MESSAGE);

JDialog dialogo = mensajeError.createDialog(this, "Mensaje de Error");

dialogo.show();

}

//EL USUARIO SE HA DADO YA DE ALTA, ENVIAMOS EL MENSAJE CORRESPONDIENTE

}else

{

System.out.println("Correcto: Puedo procesar la linea de texto");

//OBTENEMOS EL MENSAJE DEL FORMULARIO

String texto=text.getText();

//ENVIAMOS EL MENSAJE AL SERVIDOR

hebra.enviar(texto);

text.setText("");

}

}//FINAL SendMouseClicked

//DECLARACION DEL EVENTO QUE SE DEBE PRODUCIR AL CERRAR LA VENTANA DEL FORMULARIO

private void exitForm(java.awt.event.WindowEvent evt)

{

String texto=".s";//CADENA ENVIADA PARA INFORMAR AL SERVIDOR DE NUESTRA SALIDA

hebra.enviar(texto);

}//FINAL exitForm

//METODOS PARA ACCEDER RESPECTIVAMENTE A LAS VARIABLES DE TIPO JList "messages" Y "users"

public javax.swing.JList getMessagesComponent()

{

return(messages);

}

public javax.swing.JList getUsersComponent()

{

return(users);

}

//CLASE PRINCIPAL

public static void main (String args[])

{

new Client().show();

}//FIN main

//PAG 8-13

//DECLARACION DE VARIABLES

//private org.netbeans.examples.lib.timerbean.Timer timer1;

//private org.netbeans.examples.lib.timerbean.Timer timer2;

private javax.swing.JPanel jPanel1;

private javax.swing.JPanel jPanel10;

private javax.swing.JLabel jLabel2;

private javax.swing.JTextField nombreUsuario;

private javax.swing.JPanel jPanel11;

private javax.swing.JPanel jPanel12;

private javax.swing.JPanel jPanel17;

private javax.swing.JPanel jPanel18;

private javax.swing.JButton jButton1;

private javax.swing.JButton jButton2;

private javax.swing.JPanel jPanel19;

private javax.swing.JPanel jPanel2;

private javax.swing.JPanel jPanel6;

private javax.swing.JLabel jLabel1;

private javax.swing.JPanel jPanel7;

private javax.swing.JScrollPane jScrollPane2;

private javax.swing.JList messages;

private javax.swing.JPanel jPanel8;

private javax.swing.JTextField text;

private javax.swing.JPanel jPanel13;

private javax.swing.JPanel jPanel15;

private javax.swing.JPanel jPanel16;

private javax.swing.JPanel jPanel5;

private javax.swing.JScrollPane jScrollPane1;

private javax.swing.JList users;

private javax.swing.JPanel jPanel9;

private javax.swing.JButton send;

private javax.swing.JPanel jPanel3;

private javax.swing.JLabel jLabel3;

private javax.swing.JPanel jPanel4;

private javax.swing.JPanel jPanel14;

private javax.swing.JPanel jPanel20;

private javax.swing.JPanel jPanel21;

//FIN DECLARACION DE VARIABLES

private objetoCliente hebra;

private boolean nombreCorrecto;

//DECLARACION DE LA CLASE CUYOS OBJETOS (HEBRAS) SE ENCARGAN DE LA COMUNICACION CON EL SERVIDOR

//PARA PODER CREAR HEBRAS HEREDAMOS DE LA CLASE Thread

class objetoCliente extends Thread

{

//CONSTRUCTOR DE LA CLASE

public objetoCliente(Client cliente)

{

//LA HEBRA O HIJO QUE VAMOS A CREAR TOMA EL CODIGO DEL PADRE QUE VIENE PASADO POR PARAMETRO EN

//LA VARIABLE "cliente"

this.cliente=cliente;

//PAG 8-14

//CREAMOS UN VECTOR PARA ALMACENAR LOS MENSAJES ENVIADOS Y RECIBIDOS POR EL USUARIO

listaMensajes=new Vector();

//CREAMOS UN VECTOR PARA ALMACENAR UNA LISTA DE LOS USUARIOS ACTIVOS EN EL SISTEMA

listaUsuarios=new Vector();

}//FIN objetoCliente

//METODO PARA LANZAR LA HEBRA

public void run()

{

try{

//CREAMOS UN SOCKET PARA ESTABLECER LA COMUNICACION CON EL SERVIDOR EN EL PUERTO INDICADO

cli_socket=new Socket("192.168.0.1",12325);

System.out.println("Conexion con el servidor en el puerto: 12325");

//DEFINIMOS UN BUFFER O CANAL POR EL QUE RECIBIR LOS MENSAJES DEL SERVIDOR

recibido= new BufferedReader(new InputStreamReader(cli_socket.getInputStream()));

//DEFINIMOS UN BUFFER O CANAL POR EL QUE ENVIAR LOS MENSAJES AL SERVIDOR

salida= new BufferedWriter(new OutputStreamWriter(cli_socket.getOutputStream()));

while (seguir) {

//LEEMOS EL MENSAJE ENVIADO POR EL SERVIDOR

String mens=recibido.readLine();

System.out.println("Recibido: "+mens);

//ANALIZAMOS EL MENSAJE Y ACTUAMOS EN CONSECUENCIA

compruebaMensaje(mens,recibido);

}

//CONTROLAMOS EL CASO DE NO PODER ESTABLECER CONEXION CON EL SERVIDOR

}catch(Exception e) {

System.out.println("No puedo conectar con el servidor");

}

cerrar_socket();

}//FIN run

//METODO PARA COMPROBAR EL TIPO DE MENSAJE RECIBIDO

private void compruebaMensaje(String mens, BufferedReader recibido)

{

int leido=0; //PARA CONTROLAR SI ES UN MENSAJE NORMAL

System.out.println("compruebaMensaje: "+mens);

try {

if (mens.equals(CADENA_SALIR)) //MENSAJE DE SALIDA DEL SISTEMA

{

seguir=false;

cerrar_socket();

System.exit(0);

leido=1;

}else

{

if (mens.equals(CADENA_LISTA_USU)) //MENSAJE DE LISTADO DE USUARIOS

{

//RECIBIMOS EL NUMERO DE USUARIOS

Integer num=new Integer(recibido.readLine());

//PAG 8-15

System.out.println("Numero de usuarios: "+num.intValue());

//LEEMOS TANTAS VECES COMO NOS INDIQUE num

listaUsuarios.removeAllElements(); //BORRAMOS LISTADO DE USUARIOS ACTUAL

for (int i=0 ; i<num.intValue() ; i++)

{

String us=recibido.readLine();

System.out.println("Usuario: "+us);

listaUsuarios.addElement(us);

}

javax.swing.JList mes=cliente.getUsersComponent();

mes.setListData(listaUsuarios); //INTRODUCIMOS EL NUEVO LISTADO DE USUARIOS

leido=1;

//cliente.users.setListData(listaUsuarios);

}else

{

if (mens.equals(CADENA_AYUDA)) //MENSAJE DE AYUDA

{

//TRAS RECIBIR ESTE MENSAJE EL SERVIDOR NOS ENVIARA LA INFORMACION SOLICITADA QUE SE MOSTRARA

//EN LA VENTANA DE MENSAJES GLOBAL AL SER TRATADA COMO UN MENSAJE NORMAL

System.out.println("Mensaje de ayuda");

leido=1;

}else

{

if ( mens.equals(CADENA_PRIVADO)) //MENSAJE DE PRIVADO

{

System.out.println("Mensaje de privado");

leido=1;

}else

{

if (mens.length() > 9)

{

//MENSAJE DE SOLICITUD DE CONEXION (Nuevo usuario conectado)

//SOLO COMPARAMOS LOS 10 PRIMEROS CARACTERES DE LA CADENA RECIBIDA

if ( mens.substring(0,10).equals("Conectado:") )

{

System.out.println("Debo meter en la lista el Usuario: "+mens.substring(11));

//INTRODUCE EL NUEVO USUARIO EN EL VECTOR DE USUARIOS

listaUsuarios.addElement(mens.substring(11));

javax.swing.JList mes=cliente.getUsersComponent();

//ACTUALIZA LA LISTA DE USUARIOS DEL FORMULARIO CON LA NUEVA LISTA

mes.setListData(listaUsuarios);

leido=1;

}

}

//MENSAJE DE SOLICITUD DE DESCONEXION (Usuario conectado se da de baja)

if (mens.length() > 12)

{

//SOLO COMPARAMOS LOS 13 PRIMEROS CARACTERES DE LA CADENA RECIBIDA

if (mens.substring(0,13).equals("Desconectado:"))

{

System.out.println("Debo quitar de la lista el Usuario: ("+mens.substring(14)+")");

//ELIMINA DE LA LISTA DE USUARIOS EL USUARIO RECIBIDO

listaUsuarios.removeElement(mens.substring(14));

javax.swing.JList mes=cliente.getUsersComponent();

//ACTUALIZA LA LISTA DE USUARIOS DEL FORMULARIO CON LA NUEVA LISTA

mes.setListData(listaUsuarios);

leido=1;

}

}

}

}

}

}

if (leido == 0) //MENSAJE NORMAL DE DATOS

{

System.out.println("Mensaje added: "+mens);

//AÑADIMOS EL NUEVO MENSAJE A LA LISTA DE MENSAJES

listaMensajes.addElement(mens);

javax.swing.JList mes=cliente.getMessagesComponent();

//ACTUALIZAMOS LA LISTA DE MENSAJES DEL FORMULARIO CON LA NUEVA LISTA

mes.setListData(listaMensajes);

}

}catch(Exception e)

{

System.out.println("Error en mensaje recibido");

}

}//FIN compruebaMensaje

//METODO PARA ENVIAR UN MENSAJE AL SERVIDOR

public void enviar(String cadena)

//PAG 8-16

{

System.out.println("Envio: "+cadena);

try{

cadena=cadena.trim(); //QUITAMOS EL ESPACIO FINAL

cadena=cadena+"\n"; //LA CADENA DEBE TERMINAR CON "\n" PARA SER LEIDA CON "readLine"

salida.write(cadena,0,cadena.length());

salida.flush();

//CREO QUE NO HARIA FALTA PUES AL DARNOS DE BAJA EL SERVIDOR NOS MANDA ESTA CADENA Y HAY PONEMOS

//SALIR A "false"

// if ( cadena.equals(".s") )

// seguir=false;

}catch(Exception e)

{

System.out.println("Error en el envio");

seguir=false;

}

}//FIN enviar

//PERMITE CERRAR EL SOCKET Y LOS CANALES DE ENVIO Y RECEPCION DE DATOS

public void cerrar_socket()

{

try{

if (cli_socket!=null)

{

cli_socket.close();

recibido.close();

salida.close();

}

}catch(IOException e) {;}

}//FIN cerrar_socket

//PERMITE ELIMINAR EL SOCKET

public void destroy()

{

cerrar_socket();

}

//DECLARACION DE VARIABLES MIEMBRO DE LA CLASE

private Client cliente;

private BufferedReader recibido;

private BufferedWriter salida;

private Socket cli_socket;

private String cadena_leida;

private boolean seguir=true;

private Vector listaMensajes;

private Vector listaUsuarios;

private final String CADENA_SALIR=new String(".s");

private final String CADENA_LISTA_USU=new String(".u");

private final String CADENA_AYUDA=new String(".h");

private final String CADENA_PRIVADO=new String(".p");

private int pos; //PARA SABER LA POSICION DEL CARACTER "@" EN MENSAJES PRIVADOS

public String nombre_privado; //NOMBRE DEL USUARIO CON EL QUE ESTABLECEMOS UN PRIVADO

}

}

CÓDIGO DEL SERVIDOR

/*

CODIGO DEL SERVIDOR

NOMBRE DE LA CLASE Server.java

*/

//LISTA DE PAQUETES A IMPORTAR

import java.util.*;

import java.io.*;

import java.net.*;

//ESTA CLASE PRESENTA EL CODIGO DEL SERVIDOR QUE PERMITE CREAR HEBRAS O HIJOS PARA ATENDER LAS

//PETICIONES DE LOS CLIENTES

public class Server extends Object {

//CONSTRUCTOR DE LA CLASE "Server"

public Server (int puerto)

{

int serv_puerto=puerto;

int cont_conex; //PARA CONTROLAR EL NUMERO DE CONEXIONES O CLIENTES QUE ACEPTA EL SERVIDOR

try{

System.out.println("Servidor escuchando en el puerto"+puerto);

//VECTOR DE HEBRAS PARA ATENDER A LOS CLIENTES

v=new Vector();

cont_conex=0;

//CREAMOS UN SOCKET DONDE EL SERVIDOR PERMANECE ESCUCHANDO

ServerSocket sock_servidor=new ServerSocket (serv_puerto);

//ACEPTAMOS HASTA 5 USUARIOS EN EL SISTEMA

while (cont_conex<5){

//ACEPTAMOS LA CONEXION DEL CLIENTE

Socket cli_sock=sock_servidor.accept();

System.out.println("Conexion efectuada: id " +cont_conex);

//CREAMOS UNA HEBRA O HIJO QUE ATIENDA LA PETICION

objetoServidor OB=new objetoServidor(cont_conex,cli_sock,cli_sock.getInetAddress().toString(),this);

//AÑADIMOS LA NUEVA HEBRA AL VECTOR DE HEBRAS

v.addElement(OB);

//LANZAMOS LA EJECUCION DE LA HEBRA

OB.start();

cont_conex++;

}

}catch (IOException e){

e.printStackTrace();

}catch (IndexOutOfBoundsException e){

e.printStackTrace();

}

}//FIN CONSTRUCTOR Server

//PROCESA UN MENSAJE ENVIADO POR UN CLIENTE, IDENTIFICANDOLO Y ENVIANDO LA RESPUESTA ADECUADA

public static synchronized void manejaMensaje(String nombre_usu, int id_hilo,String cad)

{

int leido=0; //PARA NO TENER PROBLEMAS AL LEER CON substring

try

{

if (cad.equals(CADENA_SALIR)) //MENSAJE DE BAJA

{

salir_usu(id_hilo);

leido=1;

}

else

//PAG 8-23

{

if (cad.equals(CADENA_LISTA_USU)) //MENSAJE DE LISTADO DE USUARIOS

{

lista_usuario(id_hilo);

leido=1;

}

else

{

if (cad.equals(CADENA_AYUDA)) //MENSAJE DE AYUDA

{

mandaMensajeUno(".u lista usuarios;.s salir;.h ayuda;.p<usuario>@mensaje privado",id_hilo);

leido=1;

}

else

{

if (cad.length() > 1) //MENSAJE DE PRIVADO

{

if ( cad.substring(0,2).equals(CADENA_PRIVADO) )

{

privado_usu(cad, id_hilo, nombre_usu);

leido=1;

}

}

}

}

}

if (leido==0) //MENSAJE NORMAL DE DATOS

{

mandaMensajeTodos(nombre_usu+">"+cad);

}

}catch (StringIndexOutOfBoundsException e)

{

mandaMensajeUno("Fallo procesando mensaje, consulta ayuda <.h> ",id_hilo);

}

}//FIN manejaMensaje

//PERMITE ENVIAR UN MENSAJE A TODOS LOS USUARIOS CONECTADOS

public static synchronized void mandaMensajeTodos(String cad)

{

System.out.println("--mandaMensajeTodos");

//ACCEDEMOS A CADA UNO DE LOS CLIENTES A TRAVES DEL VECTOR DE HEBRAS

for (Enumeration e=v.elements(); e.hasMoreElements(); )

{

objetoServidor OB=(objetoServidor) e.nextElement();

OB.enviar_cad(cad);

}

}//FIN mandaMensajeTodos

//PERMITE ENVIAR UN MENSAJE A TODOS LOS USUARIOS CONECTADOS EXCEPTO AL PASADO EN "id_hilo"

public static synchronized void mandaMensajeTodosExcepto(String cad, int id_hilo)

{

for (Enumeration e=v.elements(); e.hasMoreElements(); )

{

objetoServidor OB=(objetoServidor) e.nextElement();

if (OB.id_hilo!=id_hilo)

OB.enviar_cad(cad);

}

}//FIN mandaMensajeTodosExcepto

//PERMITE ENVIAR UN MENSAJE A UN USUARIO DETERMINADO

public static synchronized void mandaMensajeUno(String cad, int id_hilo)

{

System.out.println("MandaMensajeUno: "+cad);

for (Enumeration e=v.elements(); e.hasMoreElements(); )

{

objetoServidor OB=(objetoServidor) e.nextElement();

if (OB.id_hilo==id_hilo)

//PAG 8-24

{

System.out.println("Hacemos el envio");

OB.enviar_cad(cad);

}

}

System.out.println("Tenemos en mandaMensajeUno "+v.size()+" elementos");

}//FIN mandaMensajeUno

//PERMITE MANDAR UN MENSAJE PRIVADO A UN USUARIO

public static synchronized void privado_usu(String cad, int id_hilo, String nombre_usu)

{

String nombre_privado; //NOMBRE DEL USUARIO AL QUE ENVIAMOS EL PRIVADO

String retornar; //MENSAJE A ENVIAR AL USUARIO QUE ENVIA Y EL QUE RECIBE EL PRIVADO

int pos; //PARA IDENTIFICAR LA PARTE DEL MENSAJE PRIVADO ENVIADO QUE NO ES

//USADA PARA IDENTIFICAR EL MENSAJE DE TIPO PRIVADO

pos=cad.indexOf("@");

nombre_privado=cad.substring(2,pos);

retornar=nombre_usu.concat(">").concat(nombre_privado).concat(">").concat(cad.substring(pos+1,cad.length()));

//MANDO MENSAJE AL USUARIO QUE SOLICITA PRIVADO

mandaMensajeUno(".p",id_hilo); //IDENTIFICACION DE MENSAJE

mandaMensajeUno(retornar, id_hilo); //ENVIAMOS EL MENSAJE

//OBTENGO EL id_hilo CORRESPONDIENTE AL USUARIO CON EL QUE QUIERO ESTABLECER EL PRIVADO

System.out.println("Mensaje privado para enviar a: "+nombre_privado);

for (Enumeration e=v.elements(); e.hasMoreElements(); )

{

objetoServidor OB=(objetoServidor) e.nextElement();

if (nombre_privado.equals(OB.nombre_usu))

//PAG 8-24

{

mandaMensajeUno(".p",OB.id_hilo); //IDENTIFICACION DE MENSAJE PRIVADO

System.out.println("Hacemos el envio");

mandaMensajeUno(retornar, OB.id_hilo); //ENVIAMOS EL MENSAJE

}

}

}//FIN privado_usu

//PERMITE ENVIAR LA LISTA DE USUARIOS A UN USUARIO

public static synchronized void lista_usuario(int id_hilo)

{

String mensaje;

mensaje=CADENA_LISTA_USU;

mandaMensajeUno(mensaje,id_hilo);

System.out.println("Enviando lista al cliente");

mensaje=""+v.size();

mandaMensajeUno(mensaje,id_hilo); //MANDAMOS EL NUMERO DE USUARIOS

System.out.println("Numero de usuarios: "+v.elements());//no muestra bien el valor

for (Enumeration e=v.elements(); e.hasMoreElements(); )//MANDAMOS NOMBRES DE USUARIOS 1 A 1

{

objetoServidor OB=(objetoServidor)e.nextElement();

mandaMensajeUno(OB.nombre_usu,id_hilo);

System.out.println("Usuario: "+OB.nombre_usu);

}

}//FIN lista_usuario

//PERMITE ENVIAR EL IDENTIFICADOR DE BAJA A UN USUARIO Y CIERRA LA CONEXION CON DICHO USUARIO

public static synchronized void salir_usu(int id_hilo_salir)

{

for(Enumeration e=v.elements(); e.hasMoreElements(); )

{

objetoServidor OB=(objetoServidor)e.nextElement();

if (OB.id_hilo==id_hilo_salir)

{

borrar_usu(id_hilo_salir,OB.nombre_usu);

OB.enviar_cad(CADENA_SALIR);

OB.cerrarSocket();

}

}

}//FIN salir_usu

//ELIMINAMOS LA HEBRA DEL VECTOR DE HEBRAS E INFORMAMOS AL RESTO DE USUARIOS DE LA BAJA

public static synchronized void borrar_usu(int id_hilo, String nombre_usu)

{

for(Enumeration e=v.elements(); e.hasMoreElements(); )

//PAG 8-25

{

objetoServidor OB=(objetoServidor) e.nextElement();

if (OB.id_hilo==id_hilo)

{

v.removeElement(OB);

if (nombre_usu!=null)

mandaMensajeTodosExcepto("Desconectado: "+nombre_usu,id_hilo);

}

}

}//FIN borrar_usu

//CLASE PRINCIPAL

public static void main (String args[])

{

Server serv;

serv= new Server(12325);

}//FIN main

//VARIABLES MIEMBRO DE LA CLASE SERVER

static Vector v;

public final static String CADENA_SALIR=new String(".s");

public final static String CADENA_LISTA_USU=new String(".u");

public final static String CADENA_AYUDA=new String(".h");

public final static String CADENA_PRIVADO=new String(".p");

//DECLARACION DE CLASE CUYOS OBJETOS (HEBRAS) SE ENCARGAN DE LA COMUNICACION CON LOS CLIENTES

//PARA PODER CREAR HEBRAS HEREDAMOS DE LA CLASE Thread

class objetoServidor extends Thread

{

//CONSTRUCTOR DE LA CLASE

objetoServidor(int indice, Socket sock, String dir_conex, Server servidor)

{

this.sock=sock; //ASOCIAMOS EL SOCKET AL OBJETO CREADO

this.id_hilo=indice; //PARA IDENTIFICAR LA HEBRA DE CADA CLIENTE EN EL VECTOR DE HEBRAS

this.servidor=servidor; //PARA TOMAR EL CODIGO DEL PADRE

dir_usu=new String(dir_conex); //OBTENEMOS LA DIRECCION DEL USUARIO

System.out.println("Creamos objeto servidor: "+indice);

try

{

//PAG 8-26

//CREAMOS DOS CANALES O SOCKETS, UNO DE LECTURA Y OTRO DE ESCRITURA PARA ENVIAR Y

//RECIBIR LOS MENSAJES DEL USUARIO

recibido= new BufferedReader(new InputStreamReader(sock.getInputStream()));

salida= new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

}catch (Exception e)

{

System.out.println("---------------ERROR EN LA CREACION");

e.printStackTrace();

}

}//FIN objetoServidor

//METODO PARA LANZAR LA HEBRA

public void run()

{

try

{

//ENVIAMOS UN MENSAJE AL CLIENTE INFORMANDO DEL ESTABLECIMIENTO DE LA CONEXION

String env="Conexion con el servidor efectuada";

enviar_cad(env);

//RECIBIMOS NOMBRE O NICK DEL USUARIO

nombre_usu=recibido.readLine();

System.out.println("--------------------Conectado: "+nombre_usu);

servidor.mandaMensajeTodos("Conectado: "+nombre_usu);

//ENTRAMOS EN UN BUCLE PARA ESPERAR LA LLEGADA DE MENSAJES PARA SU POSTERIOR TRATAMIENTO

while(true)

{

buffer=recibido.readLine();

buffer=tratar_buffer(buffer);

servidor.manejaMensaje(nombre_usu,id_hilo,buffer);

}

}catch (Exception e)

{

System.out.println("--------------Error");

servidor.borrar_usu(id_hilo,nombre_usu);

cerrarSocket();

}

//PAG 8-27

}//FIN run

//CONTROLAR MENSAJES DE MAS DE 80 CARACTERES

public String tratar_buffer(String buffer)

{

if (buffer.length()>79)

buffer=buffer.substring(0,79);

buffer=buffer.trim();//QUITAMOS EL ESPACIO FINAL DE LA CADENA

return(buffer);

}//FIN tratar_buffer

//PERMITE ENVIAR UN MENSAJE A UN USUARIO

public void enviar_cad(String cad_usu)

{

try

{

cad_usu.trim(); //QUITAMOS EL ESPACIO FINAL DE LA CADENA

cad_usu=cad_usu+"\n";

salida.write(cad_usu,0,cad_usu.length()); //ESCRIBIMOS EN EL CANAL DE SALIDA

salida.flush();

System.out.println("Envio Servidor: "+cad_usu);

}catch (Exception e)

{

servidor.borrar_usu(id_hilo,nombre_usu);

cerrarSocket();

}

}//FIN enviar_cad

//PERMITE CERRAR LA COMUNICACION CON EL USUARIO

public void cerrarSocket()

{

try

{

if (sock !=null)

{

sock.close(); //CERRAMOS EL SOCKET

salida.close(); //CERRAMOS EL CANAL DE SALIDA O ENVIO DE DATOS

recibido.close(); //CERRAMOS EL CANAL DE RECEPCION DE DATOS

}

}catch (Exception e)

{

e.printStackTrace();

}

}//FIN cerrarSocket

//DECLARACION DE VARIABLES MIEMBRO DE LA CLASE

private Socket sock=null;

private BufferedReader recibido;

private BufferedWriter salida;

private String buffer;

private Server servidor;

public String dir_usu;

public String nombre_usu;

public int id_hilo;

}

}

FUNCIONAMIENTO DE LA APLICACIÓN

Clase servidor padre

El primer paso para el funcionamiento correcto de la aplicación consiste en lanzar el servidor.

En el servidor tenemos un puerto conocido por todos los clientes, un vector para controlar las hebras del proceso cada una de las cuales se encargará de un cliente y un socket para establecer los canales de comunicación.

En este caso se permiten hasta 5 usuarios en el sistema.

(while (cont_conex<5))

El servidor permanece escuchando en el puerto conocido y para cada cliente que solicite una conexión creamos una nueva hebra que añadimos al vector de estas, incrementamos el número y lanzamos una nueva hebra.

C lase servidor hijo (hebras)

Una vez establecida la conexión con el cliente creamos dos canales de entrada y salida de datos respectivamente:

recibido= new BufferedReader(new InputStreamReader(sock.getInputStream()));

salida= new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

A continuación podemos distinguir 3 pasos:

  • Enviamos un mensaje al cliente informando del establecimiento de la conexión.

  • Enviamos un mensaje a cada uno de los usuarios del sistema informando de la incorporación del nuevo usuario al mismo.

  • Entramos en un bucle infinito donde esperamos las peticiones de los clientes y mediante la llamada a una función identificamos el tipo de petición y la atendemos.

servidor.manejaMensaje(nombre_usu,id_hilo,buffer);

Tipo de peticiones y respuesta a las mismas

Se pueden dar 5 tipos de mensajes:

  • Mensaje de baja

  • cad.equals(CADENA_SALIR)

    • Eliminamos la hebra correspondiente a dicho usuario del vector.

    v.removeElement(OB);

    • Informamos al resto de usuarios de la baja.

    mandaMensajeTodosExcepto("Desconectado: "+nombre_usu,id_hilo);

    • Enviamos el identificador de baja al usuario que la solicita para que termine su ejecución.

    OB.enviar_cad(CADENA_SALIR);

  • Mensaje de listado de usuarios

  • cad.equals(CADENA_LISTA_USU)

    • Enviamos mensaje de identificación.

    mensaje=CADENA_LISTA_USU;

    • Enviamos el número de usuarios.

    mensaje=""+v.size();

    • Enviamos un mensaje por cada usuario identificándolo.

    mandaMensajeUno(OB.nombre_usu,id_hilo);

  • Mensaje de ayuda

  • cad.equals(CADENA_AYUDA)

    • Enviamos mensaje con información de comandos del sistema.

    mandaMensajeUno(".u lista usuarios;.s salir;.h ayuda;.p<usuario>@mensaje privado",id_hilo);

  • Mensaje de privado

  • cad.substring(0,2).equals(CADENA_PRIVADO)

    • Envío identificación de mensaje al usuario que solicita el privado.

    mandaMensajeUno(".p",id_hilo)

    • Envío mensaje al usuario que solicita privado.

    mandaMensajeUno(retornar, id_hilo)

    • Envío identificación de mensaje al usuario con el que se solicita el privado.

    mandaMensajeUno(".p",OB.id_hilo)

    • Envío mensaje al usuario con el que se solicita el privado.

    mandaMensajeUno(retornar, OB.id_hilo)

  • Mensaje normal de datos

    • Envío el mensaje recibido a todos los usuarios

    mandaMensajeTodos(nombre_usu+">"+cad);

    Clase cliente padre

    Esta parte del código del cliente se encarga de la creación del interfaz que le permitirá al usuario interactuar con el mismo. Para ello crea un formulario donde el usuario introducirá sus mensajes y podrá recibir los mensajes del resto, esto se consigue mediante la llamada al método

    initComponents();

    Así mismo dentro de este se definen otros métodos o eventos que se producirán tras la pulsación de alguno de los botones del formulario o cuando se cierre la ventana donde este se encuentra.

    exitForm(evt);

    jButton1MouseClicked (evt);

    jButton2MouseClicked (evt);

    SendMouseClicked(evt);

    La implementación de los mismos se encuentra fuera del método initComponents()

    Al final se presenta una relación de los componentes del formulario y como se estructuran dentro de este.

    El siguiente paso consiste en crear una hebra que se encargue de la gestión de los mensajes con el servidor y a continuación lanzarla.

    C lase cliente hijo (hebra)

    El primer paso consiste en la definición de dos vectores para guardar todos los mensajes y la lista de usuarios activos en el sistema.

    Después se crea un socket, se intenta establecer conexión con el puerto conocido del servidor y definimos dos canales de entrada y salida de datos respectivamente:

    recibido= new BufferedReader(new InputStreamReader(sock.getInputStream()));

    salida= new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

    Por último entramos en un bucle infinito donde esperamos los mensajes enviados por el servidor y mediante la llamada a una función identificamos el tipo de mensaje y actuamos en consecuencia.

    compruebaMensaje(mens,recibido);

    Tipos de mensajes y actuación ante los mismos

    Se pueden dar 7 tipos de mensajes:

  • Mensaje de baja

  • mens.equals(CADENA_SALIR)

    • Salimos del bucle, cerramos el socket y terminamos la ejecución.

    seguir=false; cerrar_socket();System.exit(0);

  • Mensaje de listado de usuarios

  • mens.equals(CADENA_LISTA_USU)

    • Recibimos el número de usuarios.

    Integer num=new Integer(recibido.readLine());

    • Actualizamos lista de usuarios con los usuarios que recibimos.

    listaUsuarios.addElement(us);

    • Introducimos la nueva lista en el formulario.

    mes.setListData(listaUsuarios);

  • Mensaje de ayuda

  • mens.equals(CADENA_AYUDA)

    • Mostramos por pantalla el tipo de mensaje recibido.

    System.out.println("Mensaje de ayuda");

    • Posteriormente recibiremos como un mensaje normal de datos la información de los comandos disponibles.

    .u lista usuarios;.s salir;.h ayuda;.p<usuario>@mensaje privado

  • Mensaje de privado

  • mens.substring(0,2).equals(CADENA_PRIVADO)

    • Mostramos por pantalla el tipo de mensaje recibido.

    System.out.println("Mensaje de privado");

    • Posteriormente recibiremos como un mensaje normal de datos el mensaje privado tanto si somos el usuario que lo solicita como el que lo recibe.

    usuario_solicita>usuario_privado>mensaje

  • Mensaje de conexión

  • mens.substring(0,10).equals("Conectado:")

    • Añadimos el nuevo usuario a la lista.

    listaUsuarios.addElement(mens.substring(11));

    • Actualizamos la lista de usuarios del formulario.

    mes.setListData(listaUsuarios);

  • Mensaje de desconexión

  • mens.substring(0,13).equals("Desconectado:")

    Eliminamos el nuevo usuario a la lista.

    • listaUsuarios.removeElement(mens.substring(14));

    • Actualizamos la lista de usuarios del formulario.

    mes.setListData(listaUsuarios);

  • Mensaje normal de datos

    • Añadimos el nuevo mensaje a la lista de mensajes.

    listaMensajes.addElement(mens);

    • Actualizamos la lista de mensajes del formulario.

    mes.setListData(listaMensajes);

    Métodos llamados tras la producción de algún evento en el formulario

  • Evento que se produce tras la pulsación de botón jButton1 “SALIR”

    • Enviamos al servidor la cadena de texto “.s”

    hebra.enviar(texto);

  • Evento que se produce tras la pulsación de botón jButton2 “PRIVADO”

    • Si no hay ningún usuario seleccionado en la lista de usuarios enviamos al servidor.

    text.setText(".p<usuario>@");

    • Si hay algún usuario seleccionado en la lista de usuarios enviamos al sevidor.

    text.setText(".p".concat(users.getSelectedValue().toString()).concat("@"));

  • Evento que se produce tras la pulsación de botón send “ENVIAR”

    • Si el usuario no se ha dado de alta pero ha introducido un nick, enviamos al servidor.

    hebra.enviar(nomb);

    • Si el usuario no se ha dado de alta y no ha introducido un nick, mostramos mensaje de error.

    JOptionPane mensajeError=new JOptionPane ("No ha introducido el nombre de usuario", JOptionPane.WARNING_MESSAGE);

    • Si el usuario se ha dado de alta enviamos el mensaje al servidor.

    hebra.enviar(texto);

  • Evento que se produce al cerrar la ventana del formulario

    • Enviamos al servidor la cadena de texto “.s”

    hebra.enviar(texto);

    Relación de componentes del formulario y estructuración de los mismos

    Formulario principal (this)

    jPanel1

    JPanel13

    jpanel2

    jpanel16

    jpanel15

    jPanel1

    jPanel11

    JPanel17

    jPanel10

    jPanel18

    jPanel12

    jPanel2

    jPanel6

    jPanel7

    jPanel8

    jPanel16

    jPanel4

    JPanel3

    jPanel5

    jPanel14

    jPanel9

    jPanel10

    jPanel18

    jPanel20

    jPanel19

    jPanel20

    JButton2

    jPanel21

    jButton1

    jPanel6

    jPanel7

    jPanel8

    text

    jPanel5

    jPanel9

    El resto de (jPanel) van vacíos.

    jPanel (3, 4, 11, 12, 13, 14, 15, 17, 19, 21)

    Tipo de componentes para cada variable:

    jButton JButton1, JButton2 y send

    jLabel JLabel1, JLabel2 y JLabel3

    jScrollPane jScrollPane1 y JScrollPane2

    jTextField nombreUsuario y text

    jList messages y users

    Descripción de componentes:

    • jPanel Representa un panel o marco donde introducir otros componentes.

    • jLabel Representa una etiqueta donde escribir texto.

    • jButton Representa un botón normalmente usado para que al ser pulsado se produzca un evento.

    • jTextField Representa una caja de edición donde podemos introducir texto en tiempo de ejecución.

    • jList Pequeña ventana o marco donde iremos introduciendo texto mediante el método adecuado durante la ejecución del formulario.

    • jScrollPane Permite contener componentes en su interior, en este caso lo hemos utilizado para contener JList.

    MANUAL DEL USUARIO

    Requerimientos:

    He probado la aplicación en un Pentium 166 MMX, y la velocidad es aceptable.

    Para poder ejecutar correctamente la aplicación necesitamos un compilador de Java, concretamente yo he utilizado la versión jdk1.3.0_02 bajo Windows 98. Aunque con una anterior también nos valdría.

    Podemos obtener una versión del compilador en la dirección de internet:

    Introducir aquí la dirección www.sun.java.com

    Ejecución:

    Una vez instalado el compilador copia los archivos Client.java y Server.java en el directorio /bin del compilador. Posteriormente compilamos los ficheros, para ello y desde MS-DOS accedemos al directorio donde los acabamos de copiar y ejecutamos los siguientes comandos:

    javac Server.java

    javac Client.java

    Tras la correcta compilación estamos listos para pasar a ejecutar la aplicación. Para ello lanzamos un servidor y hasta un máximo de 5 clientes:

    • Servidor java Server

    • Cliente java Client

    Nota: La aplicación sólo funciona de forma local, para poder ejecutarse en red necesitaríamos saber la dirección IP del servidor, y modificar el código del cliente para que llamase a esa dirección en vez de utilizar la llamada a “localhost”.

    Por cada cliente lanzado tendremos una ventana con el siguiente aspecto:

    El primer paso consiste en darse de alta, para ello introducimos un nombre de usuario junto a la etiqueta usuario y enviamos el mensaje. Todos los mensajes escritos junto al botón enviar y tras pulsar dicho botón serán enviados a todos los usuarios que estén dados de alta en ese momento.

    Enviando el mensaje .h obtendrá una pequeña ayuda con todos los comandos disponibles.

    También podemos enviar un mensaje privado a uno de los usuarios de la lista. Para ello usamos la sintaxis especificada al solicitar la ayuda o elegimos el usuario en la lista y posteriormente pulsamos el botón de privado.

    5

    27

    Práctica 2: `Arquitectura Cliente-Servidor en Java'. Implementación de un chat Pág

    send

    send “ENVIAR”

    jScrollPane1

    jScrollPane1 90, 300

    jList <users>

    text

    jScrollPane2

    jScrollPane2

    jList <messages>

    Jlabel1

    Jlabel1 “Mensajes”

    jPanel21 20, 20

    jButton1 “SALIR”

    jButton2 “PRIVADO”

    jPanel19 30, 5

    jPanel20

    jLabel2

    nombreUsuario

    jLabel2 “Usuario”

    nombreUsuario 100, 28

    jPanel3 15, 220

    jPanel4 20, 25

    jPanel5 100, 325

    jPanel9

    jPanel14 15, 220

    jPanel6

    jPanel7 300, 300

    jPanel8

    jPanel10

    jPanel11 400, 10

    jPanel12 400, 10

    jPanel17 100, 10

    jPanel18

    jPanel1 200, 100

    jPanel2

    jPanel13 20, 300

    jPanel15 400, 20

    jPanel16