Mini Chat via Socket Java

Fala galera! Estou aqui desta vez para atender a um pedido de um amigo que esta tendo dificuldades em implementar um simples chat em java.

Este, será feito utilizando Socket (NÃO SABE OQUE É SOCKET???? Então clique aqui para saber).

Agora que você já sabe, vamos mostrar os códigos do servidor e cliente com suas devidas explicações.

chatserver.java


import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class chatserver extends Thread
{
  int DEFAULT_PORT=4321;
  protected int port;
  protected ServerSocket server_port;
  protected ThreadGroup CurrentConnections;
  protected Vector connections;
  protected ServerWriter writer;
  private Calendar datatual;
  //Criar um ServerSocket  public chatserver()
  {
    super("Server");
    this.port=DEFAULT_PORT;
  
    try
    {
      server_port=new ServerSocket(port);
    }
    catch (IOException e)
    {
      System.err.println(e+"Exception");
    }
    //Cria um threadgroup para as conexoes
    CurrentConnections=new ThreadGroup("Server Connections");
    //Mensagem inicial na janela do servidor    System.out.println("=== ««« Conexoes Realizadas »»» ===");
    //Um vetor para armazenar as conexoes
    connections=new Vector();
    writer=new ServerWriter(this);
    //Inicia o servidor para ouvindo as conexoes    this.start();
  }
  public void run()
  {
    try
    {
      while(true)
      {
        datatual = Calendar.getInstance();
        Socket cliente_socket=server_port.accept();
        //Exibe na janela do servidor os clientes que conectam (mostra o host
        //do cliente, a porta e a data e hora da conexao 

        System.out.println("Host:"+cliente_socket.getInetAddress()+"³ Porta:"+
        cliente_socket.getPort()+"³ "+datatual.getTime());
        Connection c=new Connection(cliente_socket,CurrentConnections,3,writer);
        //evita o acesso simultaneo        synchronized(connections)
        {
          //adiciona esta nova conexao a lista          connections.addElement(c);
        }
      }
    }
    catch(IOException e)
    {
      System.err.println(e+"Exception");
    }
  }
  //Inicia o servidor  public static void main(String[] args)
  {
    new chatserver();
  }
}
//----------------------------------------------------------------------------
class Connection extends Thread
{
  static int numberOfConnections=0;
  protected Socket client;
  protected DataInputStream in;
  protected PrintStream out;
  protected ServerWriter writer;

  public Connection(Socket cliente_socket, ThreadGroup CurrentConnections,
                                             int priority, ServerWriter writer)
  {
    super(CurrentConnections,"Connection number"+numberOfConnections++);
 
    //define a prioridade    this.setPriority(priority);
    client=cliente_socket;
    this.writer=writer;
    try
    {
      //Atarraxa os streams aos streams de entrada e saida do socket do
      //cliente e adiciona este outputstream ao vetor que contem todos
      //os streams de saida, usados pelo escritor writer

      in=new DataInputStream(client.getInputStream());
      out=new PrintStream(client.getOutputStream());
      writer.OutputStreams.addElement(out);
    }
    catch(IOException e)
    {
      try
      {
        client.close();
      }
      catch (IOException e2)
      {
        System.err.println("Exception while getting socket streams:"+e);
        return;
      }
    }
    //dispara Thread
    this.start();
  }
  //O metodo run faz um laco lendo as mensagens recebidas
  public void run()
  {
    String inline;
  
    //Envia uma mensagem de boas vindas ao cliente    out.println("Bem vindo ao MiniChat...");
    try
    {
      while(true)
      {
        //le uma linha de mensagem
        inline=in.readLine();
        //A conexao eh interrompida se null
        if (inline==null)
          break;
        //Joga a linha no escritor writer        writer.setOutdata(inline);
        synchronized(writer)
        {
          //chama o escritor synchronized() para evitar que duas linhas
          //Connection o chamem ao mesmo tempo. Esta e uma forma de "bloqueio".

          writer.notify();
        }
      }
    }
    catch(IOException e)
    {}
    finally
    {
      try
      {
        client.close();
      }
      catch(IOException e2)
      {}
    }
  }

//----------------------------------------------------------------------------
class ServerWriter extends Thread
{
  protected chatserver server;
  public Vector OutputStreams;
  public String outdata;
  private String outputline;

  public ServerWriter(chatserver s)
  {
    super(s.CurrentConnections,"Server Writer");
    server=s;
    OutputStreams=new Vector();
    this.start();
  }
  public void setOutdata(String mensagem)
  {
    outdata=mensagem;
  }
  public synchronized void run()
  {
    while(true)
    {
      //A linha faz um laco para sempre, mas na vedade so e executada quando
      //a condicao wait for reinicializada por um notify. Isso num bloco
      //sincronizado para bloquear a linha e evitar o acesso multiplo.

      try
      {
        this.wait();
      }
      catch (InterruptedException e)
      {
        System.out.println("Caught an Interrupted Exception");
      }
      outputline=outdata;
      synchronized(server.connections)
      {
        for (int i=0 ; i<OutputStreams.size() ; i++)
        {
          //Eh impressa a mensagem em cada um OutputStreams.          PrintStream out;
          out=(PrintStream)OutputStreams.elementAt(i);
          out.println(outputline);
        }
      }
    }
  }
} 


Agora que nosso server está no ar, vamos ao nosso cliente! 




ClienteCall.java


import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
public class ClienteCall extends Applet
{
  public static final int DEFAULT_PORT=4321;
  public Socket clisoc;
  private Thread reader;
  public TextArea OutputArea;
  public TextField InputArea, nomefield;
  public PrintStream out;
  public String Name;
  //Cria as linhas de leitura e escrita e as inicia.  public void init()
  {
    OutputArea=new TextArea(20,45);
    InputArea=new TextField(45);
    nomefield=new TextField(10);
  
    //Tela da Applet    add(new Label("MiniChat usando conexao (Socket TCP)"));
    add(new Label("Nome do usuario"));
    add(nomefield);
    add(OutputArea);
    add(new Label("Digite uma mensagem e pressione ENTER"));
    add(InputArea);
    resize(350,445);
    try
    {
      //Cria um socket cliente passando o endereco e a porta do servidor      clisoc=new Socket("127.0.0.1",DEFAULT_PORT);
      reader=new Reader(this, OutputArea);
      out=new PrintStream(clisoc.getOutputStream());
      //Define prioridades desiguais para que o console seja compartilhado
      //de forma efetiva.

      reader.setPriority(3);
      reader.start();
    }
    catch(IOException e)
    {
      System.err.println(e);
    }
  }
  public boolean handleEvent(Event evt)
  {
    if (evt.target==InputArea)
    {
      char c=(char)evt.key;
      if (c=='\n')
      //Vigia se o usuario pressiona a tecla ENTER.
      //Isso permite saber a mensagem esta pronta para ser enviada!

      {
        String InLine=InputArea.getText();
        Name=nomefield.getText();
        out.println(Name+">"+InLine);
        InputArea.setText("");
        //Envia a mensagem, mas adiciona o nome do usuario a ela para que os
        //outros clientes saibam quem a enviou.

        return true;
      }
    }
    return false;
  }
}
//----------------------------------------------------------------------------
//A classe Reader le a entrada do soquete e atualiza a OutputArea com as
//novas mensagens.

class Reader extends Thread
{
  protected ClienteCall cliente;
  private TextArea OutputArea;
  public Reader(ClienteCall c, TextArea OutputArea)
  {
    super("chatclient Reader");
    this.cliente=c;
    this.OutputArea=OutputArea;
  }
  public void run()
  {
    DataInputStream in=null;
    String line;
    try
    {
      in=new DataInputStream(cliente.clisoc.getInputStream());
      while(true)
      {
        line=in.readLine();
        //Adiciona a nova mensagem a OutputArea        OutputArea.appendText(line+"\r\n");
      }
    }
    catch(IOException e)
    {
      System.out.println("Reader:"+e);
    }
  }
}

Tendo isso em mãos, agora crie uma classe applet de exemplo para execução (se quiser utilizar swingão, basta criar os forms com os actionlistener e blablabla).


ClienteCall.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>Cliente do Chato</title>
  </head>
  <body>
    <applet code=ClienteCall.class archive=ClienteCall.java width=710 height=540>
    </applet>
  </body>
</html>








Pronto! nosso chat esta implementado e funcional!!! com suporte a multi thread e tudo mais!!! Se funcionou você ficará assim ------>

Abraços de seu amigo Bruno Rafael.

Veja Também:

Introdução à Socket
Upload com Primefaces
Pdf Dentro da Aplicação Swing


Comentários

Postagens mais visitadas deste blog

E Esse Tal de Nano Service?

Executar Audio em Java Swing

Validando Email em Java Com e Sem expressão Regular