segunda-feira, 22 de abril de 2013

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


Nenhum comentário:

Postar um comentário

Admin: Bruno

Olá Galera! muito grato por estarem acessando nosso blog. Espero que seja possível transmitir de forma compreensível um pouco de meus conhecimentos em programação, para esta comunidade de desenvolvedores que cresce cada vez mais! Espero que Gostem! Abraço! E meu enorme obrigado à Renato Simões, Átila Soares,Wanderson Quinto, Emerson e a toda galera que sempre ajudou meu sincero obrigado....
Especialmente a Natalia Failache e Rita de Cassia que sempre apoiaram este sonho....

De seu amigo Bruno Rafael.