CÓDIGO DEL CLIENTE /* CODIGO DEL CLIENTE NOMBRE DE LA CLASE Client.java

Anuncio
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
1
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();
2
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();
3
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) );
4
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
5
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
6
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");
7
//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);
}
8
}
);
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 ());
9
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));
10
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
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)
12
{
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;
13
//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)
{
14
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;
15
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;
16
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()
{
17
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);
18
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;
19
//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));
20
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
21
{
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") )
22
// 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;
23
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
24
//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++;
25
}
}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;
}
26
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)
{
27
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)
28
{
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
29
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
30
{
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
31
{
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
{
32
//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
33
{
//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)
34
{
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
35
{
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.
36
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
37
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
38
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
39
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);
40
• 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.
41
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
jpanel15
jpanel2
jpanel16
jPanel10
jPanel18
jPanel1
jPanel11
JPanel17
jPanel12
jPanel2
jPanel6
jPanel7
jPanel8
jPanel16
jPanel4
JPanel3
jPanel9
jPanel5
jPanel14
jPanel10
jPanel18
jPanel20
jPanel19
jPanel20
JButton2
jPanel21
jButton1
jPanel6
42
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.
43
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>
44
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
45
jPanel17 100, 10
jPanel18
jPanel1 200, 100
jPanel2
jPanel13 20, 300
jPanel15 400, 20
jPanel16
46
Descargar