You are on page 1of 5

El Servidor para el chat

En el cdigo de la clase principal del servidor hay poco que explicar puesto que
nicamente se crea el ServerSocket y un bucle infinito en el que se esperan
conexiones y cuando se producen se crea una ConexionCliente y se pone a correr
el hilo para que atienda la conexin con el cliente.

package servidorchat;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
* Servidor para el chat.
*
* author dominguez
*/
public class ServidorChat {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {

// Carga el archivo de configuracion de log4J


PropertyConfigurator.configure("log4j.properties");
Logger log = Logger.getLogger(ServidorChat.class);

int puerto = 1234;


int maximoConexiones = 10; // Maximo de conexiones simultaneas
ServerSocket servidor = null;
Socket socket = null;
MensajesChat mensajes = new MensajesChat();

try {
// Se crea el serverSocket
servidor = new ServerSocket(puerto, maximoConexiones);

// Bucle infinito para esperar conexiones


while (true) {
log.info("Servidor a la espera de conexiones.");
socket = servidor.accept();
log.info("Cliente con la IP " + socket.getInetAddress().getHostName() + " conectado.");

ConexionCliente cc = new ConexionCliente(socket, mensajes);


cc.start();

}
} catch (IOException ex) {
log.error("Error: " + ex.getMessage());
} finally{
try {
socket.close();
servidor.close();
} catch (IOException ex) {
log.error("Error al cerrar el servidor: " + ex.getMessage());
}
}
}
}

el funcionamiento del patrn observer nicamente hay que decir que mediante la funcin
setChanged() se indica que el estado del objeto observable a cambiado y adems hay que
notificrselo a sus observadores con notifyObservers(Object o) que le pasar al objeto
observador el objeto o que se quiera enviar, en nuestro caso un mensaje de un cliente
public class MensajesChat extends Observable{

private String mensaje;

public MensajesChat(){
}

public String getMensaje(){


return mensaje;
}

public void setMensaje(String mensaje){


this.mensaje = mensaje;
// Indica que el mensaje ha cambiado
this.setChanged();
// Notifica a los observadores que el mensaje ha cambiado y se lo pasa
// (Internamente notifyObservers llama al metodo update del observador)
this.notifyObservers(this.getMensaje());
}
}

finalmente la clase ConexionCliente que solo tiene dos mtodos, el mtodo run que
hereda de Thread y que es el que se encarga de recibir los mensajes del cliente y
el mtodo update que es necesario implementar por implementar la interfaz
Observer y que es el encargado de enviar el mensaje al cliente.

public class ConexionCliente extends Thread implements Observer{

private Logger log = Logger.getLogger(ConexionCliente.class);


private Socket socket;
private MensajesChat mensajes;
private DataInputStream entradaDatos;
private DataOutputStream salidaDatos;

public ConexionCliente (Socket socket, MensajesChat mensajes){


this.socket = socket;
this.mensajes = mensajes;
try {
entradaDatos = new DataInputStream(socket.getInputStream());
salidaDatos = new DataOutputStream(socket.getOutputStream());
} catch (IOException ex) {
log.error("Error al crear los stream de entrada y salida : " + ex.getMessage());
}
}

@Override
public void run(){
String mensajeRecibido;
boolean conectado = true;
// Se apunta a la lista de observadores de mensajes
mensajes.addObserver(this);

while (conectado) {
try {
// Lee un mensaje enviado por el cliente
mensajeRecibido = entradaDatos.readUTF();
// Pone el mensaje recibido en mensajes para que se notifique
// a sus observadores que hay un nuevo mensaje.
mensajes.setMensaje(mensajeRecibido);
} catch (IOException ex) {
log.info("Cliente con la IP " + socket.getInetAddress().getHostName() + " desconectado.")
;
conectado = false;
// Si se ha producido un error al recibir datos del cliente se cierra la conexion con el.
try {
entradaDatos.close();
salidaDatos.close();
} catch (IOException ex2) {
log.error("Error al cerrar los stream de entrada y salida :" + ex2.getMessage());
}
}
}
}

@Override
public void update(Observable o, Object arg) {
try {
// Envia el mensaje al cliente
salidaDatos.writeUTF(arg.toString());
} catch (IOException ex) {
log.error("Error al enviar mensaje al cliente (" + ex.getMessage() + ").");
}
}
}
la ultima clase es ConexionServidor que implementa ActionListener y que es la clase
que se llama al pulsar el botn enviar y que simplemente inicializa un
DataOutputStream en el constructor para poder recibir datos y que en
actionPerformed
(que se ejecuta cuando se hace click en el botn y de igual forma se podra ejecutar
por ejemplo al pulsar intro en el JTextField aunque esto no esta implementado)
enva el texto al servidor del chat precedido del nombre del usuario para que luego
se muestre en el chat y borra el contenido del campo de texto para que se pueda
escribir el siguiente mensaje sin tener que borrarlo manualmente.