Black Chat

Main.java



package cliente;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import servidor.Servidor;

/*************************************************************

* @author Daniel Alberto Sanchez 

* @see <a href="http://proyectosenjava.blogspot.com">proyectos en java</a>

* @version 1.0 15 de diciembre 2013    

* ***********************************************************/

public class Main extends JFrame implements ActionListener{
/**
 *
 */
private static final long serialVersionUID = 1L;
private JMenuBar menu;
private JMenu seleccion;
private JMenuItem btnCliente,btnServidor,salir;
private ImageIcon icono;
private JLabel labelFondo;

/**Crea la ventana principal de la aplicacion */

public Main(){
 super("Black Chat");
 this.setBounds(0, 0, 300, 200);
 setResizable(false);
 this.setDefaultCloseOperation(EXIT_ON_CLOSE);
 icono = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/icono.jpg"));
 this.setIconImage(icono.getImage());
 //imagen de fondo
 ImageIcon iconofondo = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/chat.jpg"));
 ImageIcon iconofondoRe = new ImageIcon(iconofondo.getImage().getScaledInstance(300, 200, 50));
 labelFondo = new JLabel(iconofondoRe);
 add(labelFondo, BorderLayout.CENTER);
 menu = new JMenuBar();
 seleccion = new JMenu("Elige");
 btnCliente = new JMenuItem("1. Cliente");
 btnServidor = new JMenuItem("2. Servidor");
 salir = new JMenuItem("3. Salir");
 seleccion.add(btnCliente);
 seleccion.add(btnServidor);
 seleccion.add(salir);
 menu.add(seleccion);
 this.setJMenuBar(menu);
 btnCliente.addActionListener(this);
 btnServidor.addActionListener(this);
 salir.addActionListener(this);
 this.setVisible(true);
}

public static void main(String[] args) {
 @SuppressWarnings("unused")
 Main m = new Main();
}

@Override
public void actionPerformed(ActionEvent ae) {
 if(ae.getSource()==btnServidor){Servidor s = new Servidor();
 s.start();
 }else if(ae.getSource()==btnCliente){
   Thread cliente = new Thread(new Cliente());
 }else if(ae.getSource()==salir){
 System.exit(0);
 }
}
}

Cliente.java


package cliente;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

public class Cliente extends JFrame implements Runnable, ActionListener,WindowListener,KeyListener{
  private Socket s;
  private ObjectOutputStream oos;
  private ObjectInputStream ois;
  private PanelPersonal inferior,superior,inferiorMensaje,inferiorOpciones,emoticones;
  private JSplitPane medio;
  private JTextField ip,puerto,mensaje;
  private JButton conectar,enviar;
  private JTextPane areaTexto,areaClientes;
  private Thread t;
  private JScrollPane scroll,scrollClientes;
  private JLabel labelIp,labelPuerto,labelMensaje;
  private MensajeAEnviar envio;
  private JToggleButton negrita,cursiva,subrayado;
  private JComboBox tamanoLetra,boxColores,familia;
  public Color color;
  private ArrayList<JToggleButton> caritas;
  private ArrayList<Icon> caritasSeleccionadas,caritasRecibidas;
  private HashMap<String,Color> colores;
  private String fuentes[];
  private boolean seguirEspera;
  private ArrayList<String> conectados = new ArrayList<String>();
  private String usuario;  

  /**Se crea la ventana cliente del chat*/

  public Cliente(){
    super("Black Chat Cliente");
    this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    this.setBounds(0, 0, 800, 800);
    ImageIcon icono = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/icono.jpg"));
    this.setIconImage(icono.getImage());    
    setResizable(false);
    //panel superior
    superior = new PanelPersonal();
    superior.setLayout(new FlowLayout());
    ip = new JTextField(30);
    puerto = new JTextField(7);
    conectar = new JButton("Conectar (F1)");
    labelIp = new JLabel("Ip: ");
    labelIp.setForeground(Color.WHITE);
    labelPuerto = new JLabel("Puerto: ");
    labelPuerto.setForeground(Color.WHITE);
    superior.add(labelIp);
    superior.add(ip);
    superior.add(labelPuerto);
    superior.add(puerto);
    superior.add(conectar);
    this.add(superior,BorderLayout.NORTH);
    //panel medio
    medio = new JSplitPane();
    areaTexto = new JTextPane();
    areaTexto.setEditable(false);
    areaClientes = new JTextPane();
    areaClientes.setEditable(false);
    scroll = new JScrollPane(areaTexto);
    scrollClientes = new JScrollPane(areaClientes);
    areaTexto.setPreferredSize(new Dimension(500,medio.getHeight()-20));
    areaClientes.setPreferredSize(new Dimension(200,medio.getHeight()-20));
    medio.add(scroll,JSplitPane.RIGHT);
    medio.add(scrollClientes,JSplitPane.LEFT);   
    this.add(medio,BorderLayout.CENTER);   
    //panel inferior
    inferior = new PanelPersonal();
    inferior.setLayout(new GridLayout(3,1,10,10));
    inferiorMensaje = new PanelPersonal();
    inferiorMensaje.setLayout(new FlowLayout());
    inferiorOpciones = new PanelPersonal();
    inferiorOpciones.setLayout(new FlowLayout());
    mensaje = new JTextField(50);
    labelMensaje = new JLabel("Mensaje: ");
    labelMensaje.setForeground(Color.WHITE);
    enviar = new JButton("Enviar");
    inferiorMensaje.add(labelMensaje);
    inferiorMensaje.add(mensaje);
    inferiorMensaje.add(enviar);
    inferior.add(inferiorMensaje);
    negrita = new JToggleButton("N");
    cursiva = new JToggleButton("C");
    subrayado = new JToggleButton("S");
    boxColores = new JComboBox();
    definirColores();
    boxColores.setBackground(Color.BLACK);
    boxColores.setForeground(Color.WHITE);
    int tam[] = {10,11,12,14,16,18,20,22,24,32,48,72};
    tamanoLetra = new JComboBox();
    for(int n:tam)tamanoLetra.addItem(n);
    GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
    fuentes= environment.getAvailableFontFamilyNames();
    familia=new JComboBox(fuentes);
    inferiorOpciones.add(boxColores);
    inferiorOpciones.add(familia);
    inferiorOpciones.add(tamanoLetra);
    inferiorOpciones.add(negrita);
    inferiorOpciones.add(cursiva);
    inferiorOpciones.add(subrayado);
    inferior.add(inferiorOpciones);
    emoticones = new PanelPersonal();
    emoticones.setLayout(new FlowLayout());
    inicializarEmoticones();
    inferior.add(emoticones);
    this.add(inferior,BorderLayout.SOUTH);
    enviar.addActionListener(this);
    conectar.addActionListener(this);
    this.setVisible(true);
    this.addWindowListener(this);
    mensaje.addKeyListener(this);
    ip.addKeyListener(this);
    puerto.addKeyListener(this);
  }  

  /**hilo que recibe los mensajes*/ 

  @Override
  public void run() {
    seguirEspera=true;
    while(seguirEspera){
      recibirMensaje();
    }
  }

  //acciones de la interface ActionListener

  @Override
  public void actionPerformed(ActionEvent ae) {
    if(ae.getSource()==enviar){
      enviarMensaje();
    }else if(ae.getSource()==conectar){
      conectarAlServidor();
    }
  }
  /**metodo que conecta al servidor*/  

  public void conectarAlServidor(){
    try {
      s = new Socket(ip.getText(),Integer.parseInt(puerto.getText()));
      s.setSoLinger(true, 20);
      oos = new ObjectOutputStream(s.getOutputStream());
      ois = new ObjectInputStream(s.getInputStream());   
      InetAddress ia = InetAddress.getLocalHost();
      usuario = ia.getHostName();
      envio = null;
      String cad =(String) familia.getSelectedItem();
      envio = new MensajeAEnviar("Se conecto : "+usuario,cad,Color.RED,14,false,false,false,null,usuario);
      oos.writeObject(envio);
      ip.setEditable(false);
      puerto.setEditable(false);
      conectar.setEnabled(false);
    } catch (NumberFormatException e) {
      e.printStackTrace();
    } catch (UnknownHostException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    t = new Thread(this);
    t.start();
  }

  //metodo que envia los mensajes 
  public void enviarMensaje(){
    try {
      envio = null;
      String nombre = (String) boxColores.getSelectedItem();
      color = colores.get(nombre);
      ObtenerCaritas();
      String cad =(String) familia.getSelectedItem();
      envio = new MensajeAEnviar(mensaje.getText(),cad,color,Integer.parseInt(tamanoLetra.getSelectedItem().toString()),negrita.isSelected(),cursiva.isSelected(),subrayado.isSelected(),caritasSeleccionadas,usuario);
      oos.writeObject(envio);
      borrarCampos();
    } catch (IOException e) {
      e.printStackTrace();
    }
  } 
  /**Metodo que envia los mensajes*/
  public void enviarMensaje(String msg){
    try {
      envio = null;
      String nombre = (String) boxColores.getSelectedItem();
      color = colores.get(nombre);
      ObtenerCaritas();
      String cad =(String) familia.getSelectedItem();
      envio = new MensajeAEnviar(msg,cad,color,Integer.parseInt(tamanoLetra.getSelectedItem().toString()),negrita.isSelected(),cursiva.isSelected(),subrayado.isSelected(),caritasSeleccionadas,usuario);
      oos.writeObject(envio);
      borrarCampos();
    } catch (IOException e) {
      e.printStackTrace();
    }
  } 

  /**metodo que recibe los mensajes*/ 
  public void recibirMensaje(){
    try {
      SimpleAttributeSet attrs = new SimpleAttributeSet();
      envio = null;
      envio = (MensajeAEnviar) ois.readObject();
      String msg = envio.getMensaje();
      color = envio.getColor();
      int tamano = envio.getTamano();
      String cad = envio.getFamilia();
      caritasRecibidas = envio.getCaritas();
      StyleConstants.setBold(attrs, true);
      //Si se desconecto un cliente
      if(envio.getMensaje().equals("chau")){
        areaTexto.getStyledDocument().insertString(areaTexto.getStyledDocument().getLength(),envio.getEmisor()+": se desconecto\n", attrs);
        borrarConectado(envio.getEmisor());
        return;
      }
      //Un mensaje comun que sera escrito en el area de mensajes
      if(!envio.getMensaje().equals("confirmacion")){
        if(envio.getMensaje().indexOf("Se conecto")<0){
          areaTexto.getStyledDocument().insertString(areaTexto.getStyledDocument().getLength(),envio.getEmisor()+": ", attrs);
        }
        StyleConstants.setForeground(attrs, color);
        StyleConstants.setFontFamily(attrs, cad);
        StyleConstants.setFontSize(attrs, tamano);
        StyleConstants.setBold(attrs, envio.isNegrita());
        StyleConstants.setItalic(attrs, envio.isCursiva());
        StyleConstants.setUnderline(attrs, envio.isSubrayado());
        areaTexto.getStyledDocument().insertString(areaTexto.getStyledDocument().getLength(),msg, attrs);
        if(caritasRecibidas!=null){
          for(int z =0; z<caritasRecibidas.size();z++){
            areaTexto.setCaretPosition(areaTexto.getStyledDocument().getLength());
            areaTexto.insertIcon(caritasRecibidas.get(z));
          }
        }
        areaTexto.getStyledDocument().insertString(areaTexto.getStyledDocument().getLength(),"\n", attrs);
      }
      llenarAreaClientes(envio.getEmisor());
      //Si se conecto un cliente se envia mensaje de confirmacion
      if(envio.getMensaje().indexOf("Se conecto")>=0){
        enviarMensaje("confirmacion");
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (BadLocationException e) {
      e.printStackTrace();
    }
  }  

  /**metodo que carga los emoticones*/  

  public void inicializarEmoticones(){
    caritas = new ArrayList<JToggleButton>();
    ImageIcon icono1 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Crying.jpg"));
    caritas.add(new JToggleButton(icono1));
    ImageIcon icono2 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Devil.jpg"));
    caritas.add(new JToggleButton(icono2));
    ImageIcon icono3 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Happy.jpg"));
    caritas.add(new JToggleButton(icono3));
    ImageIcon icono4 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Mad.jpg"));
    caritas.add(new JToggleButton(icono4));
    ImageIcon icono5 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Sad.jpg"));
    caritas.add(new JToggleButton(icono5));
    ImageIcon icono6 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Shocking.jpg"));
    caritas.add(new JToggleButton(icono6));
    ImageIcon icono7 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Sleep.jpg"));
    caritas.add(new JToggleButton(icono7));
    ImageIcon icono8 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Tounge.jpg"));
    caritas.add(new JToggleButton(icono8));
    ImageIcon icono9 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/What.jpg"));
    caritas.add(new JToggleButton(icono9));
    ImageIcon icono10 = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/Wink.jpg"));
    caritas.add(new JToggleButton(icono10));
    for(JToggleButton ic:caritas)emoticones.add(ic);
  }
 

  /**metodo que obtiene los emoticones seleccionados para ser enviados*/  

  public void ObtenerCaritas(){
    caritasSeleccionadas = null;
    caritasSeleccionadas = new ArrayList<Icon>();
    for(int n=0; n<caritas.size(); n++){
      if(caritas.get(n).isSelected())caritasSeleccionadas.add(caritas.get(n).getIcon());
    }
  } 

  /**metodo que carga los colores de las letras*/  

  public void definirColores(){
    colores = new HashMap<String ,Color>();
    colores.put("Negro",Color.BLACK);
    boxColores.addItem("Negro");
    colores.put("Blanco",Color.WHITE);
    boxColores.addItem("Blanco");
    colores.put("Rojo",Color.RED);
    boxColores.addItem("Rojo");
    colores.put("Azul",Color.BLUE);
    boxColores.addItem("Azul");
    colores.put("Verde",Color.GREEN);
    boxColores.addItem("Verde");
    colores.put("Amarillo",Color.YELLOW);
    boxColores.addItem("Amarillo");
    colores.put("Gris",Color.GRAY);
    boxColores.addItem("Gris");
    colores.put("Cyan",Color.CYAN);
    boxColores.addItem("Cyan");
    colores.put("Rosa",Color.PINK);
    boxColores.addItem("Rosa");
  }  

  /**metodo que limpia los campos cuando el mensaje ya fue enviado*/ 

  public void borrarCampos(){
    mensaje.setText("");
    for(int b=0;b<10;b++){
      caritas.get(b).setSelected(false);
    }
    negrita.setSelected(false);
    subrayado.setSelected(false);
    cursiva.setSelected(false);
  } 

  /**metodo que muestra los clientes conectados*/
 

  public void llenarAreaClientes(String cliente){    
    StringBuilder builder = new StringBuilder();
    builder.setLength(0);
    SimpleAttributeSet attrs = new SimpleAttributeSet();
    boolean encontrado = buscaCliente(cliente);
    if(!encontrado){
      conectados.add(cliente);
    }
    for(String c:conectados)builder.append(c+"\n");
    try {
      areaClientes.setText("");
      areaClientes.getStyledDocument().insertString(areaClientes.getStyledDocument().getLength(),builder.toString(), attrs);
    } catch (BadLocationException e) {
      e.printStackTrace();
    }
  }  

  /**metodo busca si el cliente esta entre los conectados*/ 

  public boolean buscaCliente(String cliente){
    boolean encontrado = false;
    for(String c:conectados){
      if(c.equals(cliente)){
        encontrado=true;
      }
    }
    return encontrado;
  }  

  /**metodo borrar cliente que se desconecta*/ 

  public void borrarConectado(String cliente){
    conectados.remove(cliente);
    StringBuilder builder = new StringBuilder();
    builder.setLength(0);
    SimpleAttributeSet attrs = new SimpleAttributeSet();
    for(String c:conectados)builder.append(c+"\n");
    try {
      areaClientes.setText("");
      areaClientes.getStyledDocument().insertString(areaClientes.getStyledDocument().getLength(),builder.toString(), attrs);
    } catch (BadLocationException e) {
      e.printStackTrace();
    }
  }
  
  //metodos de la interface WindowListener
 
  public void windowActivated(WindowEvent we) {    
  }

  public void windowClosed(WindowEvent we) {
  }
  
  public void windowClosing(WindowEvent we) {
    if(s!=null){
      String cad =(String) familia.getSelectedItem();
      envio = new MensajeAEnviar("chau",cad,Color.RED,14,false,false,false,null,usuario);
      try {
        oos.writeObject(envio);
        oos.flush();
        seguirEspera=false;
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    this.dispose();
  }

  public void windowDeactivated(WindowEvent we) {   

  }
  
  public void windowDeiconified(WindowEvent we) {   

  }

  public void windowIconified(WindowEvent we) {   

  }

  public void windowOpened(WindowEvent we) { 

  }
  //Metodos de la interface KeyListener

  @Override
  public void keyTyped(KeyEvent e) {  

  }
  @Override
  public void keyPressed(KeyEvent e) {  

  }
  @Override
  public void keyReleased(KeyEvent e) {
    if(e.getKeyCode()==KeyEvent.VK_ENTER){
      enviarMensaje();
    }else if(e.getKeyCode()==KeyEvent.VK_F1){
      conectarAlServidor();
    }
  } 
}

MensajeAEnviar.java


package cliente;

import java.awt.Color;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.Icon;

public class MensajeAEnviar implements Serializable{

private String mensaje;
private Color color;
private int tamano;
private boolean negrita,cursiva, subrayado;
private ArrayList<Icon> caritas;
private String familia;
private String emisor;

/**Clase bean que sirve para guardar las caracteristicas del mensaje,
 * como el mensaje en si mismo */

public MensajeAEnviar(String mensaje,String familia, Color color, int tamano,boolean negrita, boolean cursiva, boolean subrayado, ArrayList<Icon> caritas,String emisor){
 this.mensaje = mensaje;
 this.color = color;
 this.tamano = tamano;
 this.negrita = negrita;
 this.cursiva = cursiva;
 this.subrayado = subrayado;
 this.caritas = caritas;
 this.familia = familia;
 this.emisor = emisor;
}
//Metodos setter y getter

public String getFamilia() {
 return familia;
}

public void setFamilia(String familia) {
 this.familia = familia;
}

public ArrayList<Icon> getCaritas() {
 return caritas;
}

public void setCaritas(ArrayList<Icon> caritas) {
 this.caritas = caritas;
}

public boolean isNegrita() {
 return negrita;
}

public void setNegrita(boolean negrita) {
 this.negrita = negrita;
}

public boolean isCursiva() {
 return cursiva;
}

public void setCursiva(boolean cursiva) {
 this.cursiva = cursiva;
}

public boolean isSubrayado() {
 return subrayado;
}

public void setSubrayado(boolean subrayado) {
 this.subrayado = subrayado;
}

public String getMensaje() {
 return mensaje;
}

public void setMensaje(String mensaje) {
 this.mensaje = mensaje;
}

public Color getColor() {
 return color;
}

public void setColor(Color color) {
 this.color = color;
}

public int getTamano() {
 return tamano;
}

public void setTamano(int tamano) {
 this.tamano = tamano;
}

  public String getEmisor() {
    return emisor;
  }

  public void setEmisor(String emisor) {
    this.emisor = emisor;
  }

}

PanelPersonal.java


package cliente;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JPanel;

public class PanelPersonal extends JPanel {
  private Color color1 = new Color(0,0,0);
  private Color color2 = new Color(100,100,100); 

  /**Panel con efecto degradado de fondo, pueden variarse
  * los colores y asi optar por distintos fondos*/ 

  public PanelPersonal(){
    this.setVisible(true);
  }  

  public Color getColor1() {
    return color1;
  }

  public void setColor1(Color color1) {
    this.color1 = color1;
  }

  public Color getColor2() {
    return color2;
  }

  public void setColor2(Color color2) {
    this.color2 = color2;
  }

    @Override
  protected void paintComponent(Graphics g){
    Graphics2D g2 = (Graphics2D) g.create();
    Rectangle clip = g2.getClipBounds(); 
    g2.setPaint(new GradientPaint(0.0f,0.0f,color1.darker(),this.getWidth(),this.getHeight(),color2.darker()));
    g2.fillRect(clip.x, clip.y, clip.width, clip.height);
  }
}

Servidor.java


package servidor;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Servidor extends Thread{

  private Socket s;
  private ServerSocket ss;
  private ArrayList<AtenderClientes> listaClientes;
  private VentanaServidor vs;
  private final int puerto = 9998 ;
  private Log log;
  private ArrayList<String> clientes;
  private int numCliente;
  private boolean seguir = true;

  /**hilo principal del servidor, solo crea hilos de la clase AtenderClientes y los pone
  en una lista de clientes*/
  
    @Override
  public void run(){
    clientes = new ArrayList<String>();
    try {
      System.out.println();
      ss = new ServerSocket(puerto);
    } catch (IOException e) {
      e.printStackTrace();
    }
    this.vs = new VentanaServidor(this.ss,this);
    listaClientes = new ArrayList<AtenderClientes>();
    vs.getActividad().setText(vs.getActividad().getText()+"\n"+"Creando lista de clientes ...");
    vs.getActividad().setText(vs.getActividad().getText()+"\n"+"Abriendo servidor en puerto 9998 ...");
    vs.getActividad().setText(vs.getActividad().getText()+"\n"+"Servidor Listo !!!");
    log = new Log();
    while(seguir){
      try {
        s = ss.accept();
        s.setSoLinger(true, 20);
        log.escribir("Se conecto: "+s.getInetAddress().getHostName());
      } catch (IOException e) {
        e.printStackTrace();
      }
      numCliente++;
      clientes.add(s.getInetAddress().getHostAddress());
      AtenderClientes ac = new AtenderClientes(s,this,numCliente);
      listaClientes.add(ac);
      ac.start();          
      vs.getActividad().setText(vs.getActividad().getText()+"\n"+"Se conecto: "+s.getInetAddress().getHostName());      
    }  
  }  

  /**metodo de envio de los mensajes a todos los clientes*/

  public synchronized void broadcast(Object aux){
    for(AtenderClientes ac:listaClientes){
      try {
        if(!ac.getCliente().isClosed()){
          ac.getOos().writeObject(aux);
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }  

  /**metodo que borra de la lista de clientes a aquellos que salen del chat*/
  public void borrarCLiente(AtenderClientes ac){
    this.getVs().getActividad().append("\nSe desconecto: "+ac.getCliente().getInetAddress().getHostName());
    clientes.remove(ac.getCliente().getInetAddress().getHostAddress());
    log.escribir("Se desconecto: "+ac.getCliente().getInetAddress().getHostName());
    this.listaClientes.remove(ac);
  } 

  //metodos getter y setter necesarios
  public ArrayList<AtenderClientes> getListaClientes() {
    return listaClientes;
  }
  
  public void setListaClientes(ArrayList<AtenderClientes> listaClientes) {
    this.listaClientes = listaClientes;
  }

  public VentanaServidor getVs() {
    return vs;
  }

  public void setVs(VentanaServidor vs) {
    this.vs = vs;
  }

  public ArrayList<String> getClientes() {
    return clientes;
  }

  public void setClientes(ArrayList<String> clientes) {
    this.clientes = clientes;
  }
 

  public ServerSocket getSs() {
    return ss;
  }

  public void setSs(ServerSocket ss) {
    this.ss = ss;
  } 

  public int getPuerto() {
    return puerto;
  } 
}

AtenderClientes.java


package servidor;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import cliente.MensajeAEnviar;

public class AtenderClientes extends Thread{

  private Socket cliente;
  private ObjectOutputStream oos;
  private ObjectInputStream ois;
  private Servidor ss;
  /**Se utilizo para diferenciar varios clientes corriendo en un host local,
  * es un numero de orden de conexion, se entiende que no habra ip
  * duplicadas en un red local (evitando asi errores) por lo que se puede
  * optar por omitirlo o dejarlo*/
  private int num; 
  /**Se crea una clase por cada cliente*/
  public AtenderClientes(Socket cliente,Servidor ss,int num){
    this.cliente = cliente;
    this.ss=ss;
    this.num=num;
  } 

  /**hilo que atiende las peticiones de un cliente en particular*/ 

    @Override
  public void run(){
    try {
      oos = new ObjectOutputStream(cliente.getOutputStream());
      ois = new ObjectInputStream(cliente.getInputStream());
    } catch (IOException e) {
      e.printStackTrace();
    }
    while(true){
      try {
        Object aux = ois.readObject();
        MensajeAEnviar aux2 = (MensajeAEnviar) aux;
        String cad = aux2.getMensaje();
        if(cad.equals("chau")){
          aux2.setEmisor(num+" - "+aux2.getEmisor());
          ss.broadcast(aux2);
          this.desconectar();
          break;
        }
        aux2.setEmisor(num+" - "+aux2.getEmisor());
        ss.broadcast(aux2);
      } catch (IOException e) {
        e.printStackTrace();
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      }
    }
  }

  /**metodo que desconecta al cliente del servidor*/ 

  public void desconectar(){
    ss.borrarCLiente(this);
    try {
      this.oos.close();
      this.ois.close();
      this.cliente.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  } 

  //metodos getter y setter necesarios 
  public Socket getCliente() {
    return cliente;
  }
  
  public void setCliente(Socket cliente) {
    this.cliente = cliente;
  }
  
  public ObjectOutputStream getOos() {
    return oos;
  }
  
  public void setOos(ObjectOutputStream oos) {
    this.oos = oos;
  } 

}

VentanaServidor.java


package servidor;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class VentanaServidor extends JDialog implements WindowListener {

  private JLabel label;
  private JTextArea actividad;
  private JScrollPane scroll;
  private ServerSocket s = null;
  private Servidor servidor;
  /**
  * Crea la ventana que ira mostrando informacion de la actividad del chat
  */
  public VentanaServidor(ServerSocket s,Servidor servidor) {
    this.s = s;
    this.servidor = servidor;
    setTitle("Black Chat Servidor");
    this.setSize(600, 400);
    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setResizable(false);
    ImageIcon icono = new ImageIcon(this.getClass().getClassLoader().getResource("recursos/icono.jpg"));
    this.setIconImage(icono.getImage());
    actividad = new JTextArea();
    actividad.setBackground(Color.BLACK);
    actividad.setForeground(Color.WHITE);
    scroll = new JScrollPane(actividad);
    StringBuilder sb = new StringBuilder();
    try {
      String host = InetAddress.getLocalHost().getHostName();
      sb.append("IP: " + s.getInetAddress().getByName(host));
      sb.append("   Nombre Host: " + s.getInetAddress().getByName(host).getHostName());
      sb.append("   Puerto: 9998");
    } catch (UnknownHostException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    label = new JLabel(sb.toString());
    this.add(label, BorderLayout.NORTH);
    this.add(scroll, BorderLayout.CENTER);
    addWindowListener(this);
    this.setVisible(true);
  }
  
  /*Metodos getter y setter*/
  public JTextArea getActividad() {
    return actividad;
  }
  
  public void setActividad(JTextArea actividad) {
    this.actividad = actividad;
  }

  //Metodos de la interface WindowListener
  @Override
  public void windowOpened(WindowEvent e) {
  }

  @Override
  public void windowClosing(WindowEvent e) {
    if (s!=null) {
      try {
        servidor.stop();
        s.close();
      } catch (IOException ex) {
        Logger.getLogger(VentanaServidor.class.getName()).log(Level.SEVERE, null, ex);
      }
    }
  }

  @Override
  public void windowClosed(WindowEvent e) {
  }

  @Override
  public void windowIconified(WindowEvent e) {
  }
  
  @Override
  public void windowDeiconified(WindowEvent e) {
  }

  @Override
  public void windowActivated(WindowEvent e) {
  }
  
  @Override
  public void windowDeactivated(WindowEvent e) {
  }
}

Log.java


package servidor;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

public class Log {  

  File f;
  FileWriter fw;
  BufferedWriter bw;
  PrintWriter pw;
  Date date; 

  /** Crea el log del chat*/

  public Log(){
    f = new File("log.txt");
    date = new Date();
    try {
      fw = new FileWriter(f);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }  

  /**metodo que guarda la actividad del chat en el archivo log.txt*/ 
  public void escribir(String texto){
    try {
      bw = new BufferedWriter(fw);
      pw = new PrintWriter(bw);
      pw.append(date+": "+texto+"\n");
      pw.flush();
      bw.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Imagenes del Programa








Archivo log.txt generado




El chat ejecutandose


Los archivos del proyecto

https://drive.google.com/folderview?id=0B0sBXdZ8aJgdMUpLM0tVT3ZrcHM&usp=sharing

El proyecto en sourceforge.net

https://sourceforge.net/projects/bl4ckchat

Comentarios