Chat em java usando Socket e Thread

61 respostas
V

Ola boa tarde eu sei que tem muita gente que não gosta disso mas preciso de uma ajuda o mais urgente possivel:eu sou aluno de segundo semestre de sistemas para internet(webdesigner) e tenho uma matéria chamada ambiente web aonde meu professor pediu o seguinte exercicio:
[size=18][b]Crie um chat com a linguagem de programação Java utilizando Socket e Thread.

Este programa deve ter um servidor que permita que vários cliente se conectem e conversem entre si. Quando o usuário A enviar uma mensagem para o servidor ela deve ser retransmitida para todos os clientes conectados.[/b][/size]

Este exercicio vale nota e como estou mal nessa materia e o professor masl explicou socjket e thread eu gostria se fosse possivel que vc me ajudasem enviando o código, se possivel antes do dia 21/11, pis como fui mal na prova corro o rusco de pegar dp, se puderem me ajudar agradeço se não agradeço do mesmo jeito

obrigado

victor hugo

61 Respostas

W

mano, tu veio no forum errado, ngm aqui vai te passar o codigo pronto, mas…
se vc quiser tentar fazer e surgirem duvidas te garanto q elas serão resolvias pelo pessoal aqui :slight_smile:

V

obrigado cara, bom vamos ver eu fiz assim:
esse éo cliente:

import java.net.;
import java.io.
;

public class Cliente extends Thread

{

private String server;

private int porta;
public Cliente(String server, int porta){   
     this.server = server;   
     this.porta = porta;   
 }   

 public static void main(String[] args){   
      try{   
           String server = "localhost";   
           int porta = 1000;   
           int numeroDeClientes = 3;   

           for(int i=0; i < numeroDeClientes; i++){   

               new Cliente(server, porta).start();   

        }   

      }catch(Exception e){   
           e.printStackTrace();   
      }   
 }   


 public void run(){   
      try{   

               while(true){   

                     Socket s = new Socket(server, porta);   

                     System.out.println("Conectado a " + server + ":" + porta);   

                     ObjectOutputStream oo = new ObjectOutputStream(s.getOutputStream());   

                     oo.writeObject("Soh!");   

                     s.close();   
           }   

      }catch(Exception e){   
           e.printStackTrace();   
      }   
 }

}

e esse éo servidor:

import java.net.;
import java.io.
;

public class Servidor implements Runnable

{

ServerSocket ss;
public Servidor(int porta) throws Exception{   
      ss = new ServerSocket(porta);   

      new Thread(this).start();   

      System.out.println("Servidor ouvindo na porta:" + porta);   

    }   

 public void run(){   
      try{   
           while(true){   
                new TrataCliente(ss.accept()).start();   
                System.out.println("Mais um cliente atendido!");   

           }   

      }catch(Exception e){   
           e.printStackTrace();   
           System.exit(1);   
      }   
 }   
 public static void main(String[] args){   
      try{   
           new Servidor(1000);   

      }catch(Exception e){   
           e.printStackTrace();   
           System.exit(1);   
      }   
 }

}

class TrataCliente extends Thread

{

private Socket client;
public TrataCliente(Socket s){   
      client = s;   
 }   

 public void run(){   
      try{   
           // aqui vai a sua comunicacao com o cliente   
           ObjectInputStream oi = new ObjectInputStream(client.getInputStream());   

           System.out.println("Chegou isso:" + oi.readObject());   

           client.close();}   

      catch(Exception e){   
           e.printStackTrace();   
           System.exit(1);   
      }   
 }

}
se estiver certo me avise, se não me avise aonde posso conseguir o código pois realmente tenho bastante dificuldade com a lingaugem Java e realmente tenho vontade de aprender e aprender bem mesmo, se puderem me indicar algum material tb que me facilite a aprender essa lingaugem.

obrigado

V

Quando postar códigos, use a tag code como descrito aqui:
http://www.guj.com.br/posts/list/50115.java

V

mas é só na parte de socket e thread que não entendie fui mal só na primeira prova, mal em termos aceretei quase a metade da prova, se puderem me indicar, um lugar aonde posso achar esse código

M

Veja se isso te ajuda:

http://www.guj.com.br/java.tutorial.artigo.20.1.guj

V

Algumas dicas:

  1. O cliente não terá mais de uma thread. Só o server.
  2. O servidor terá 1 thread para esperar os clientes (método accept) e uma thread para cada cliente criado;
  3. Cada cliente que for criado deve ser colocado num List. Assim, quando uma mensagem chegar, você pode redistribuir para os outros clientes;
  4. Não utilize o ObjectOutputStream, no lugar, pense no DataOuputStream. Por lá tem um método readUTF, que deve ser mais fácil de usar no seu caso.
G

alguem pode me ajudar???
não estou conseguindo reenviar a todos os clientes…
criei um
List Lista = new ArrayList(); // onde guarda a porta dos clientes…
quero q toda a mensagem que chegue até ela seja reenviada a todos os clientes…

segue o codigo…

try {
String mensagem;

outS = conexao.getOutputStream();
        inputS = conexao.getInputStream();
        outDS = new DataOutputStream(outS);
        inD = new DataInputStream(inputS);

        mensagem = inD.readUTF();
        servidor.telaLog.append("Data: " + getData() + "\n");
        servidor.telaLog.append("  Mensagem recebida de " + conexao.getPort() + "\n");
        servidor.telaLog.append(mensagem + "\n\n");
        outDS.writeUTF(mensagem);

    }
V

Comece fazendo o que eu já falei ali em cima, e leia o link:
http://www.guj.com.br/posts/list/50115.java

J

Estou revivendo esta thread, porque acho que o assunto aqui tem a ver com a minha dúvida.
Tenho uma aplicação que faz várias requisições via socket para uma outra máquina, sendo que, estas requisições são dividas em threads, por exemplo, cada thread pode enviar 200 requisições, mas se eu tenho 3 threads enviando 200 threads a minha aplicação “perde” desempenho. Porque quando eu faço as requisições com 1 thread enviando 200 requisições eu recebo do outro lado umas 100 por segundo, quando eu coloco mais threads esta média cai para umas 50 a 40 por segundo.
A minha dúvida é esta, eu tenho que rever o código? Ou tenho que configurar algo na jvm? Ou configurar algo na máquina de envio? Ou fazer as três opções?
O meu sistema operacional é Red Hat 4.1.2-14, eu uso a jvm6 e para cirar as threads eu uso a java.util.concurrent.*, e para enviar as requisições eu uso java.net.Socket.

V

A melhor forma de lidar com threads de pequena duração é através de um thread pool.

Um thread pool nada mais é do que um grupo de threads que nunca (ou quase nunca) morrem. Essas threads são preparadas para receber vários runnables, ou entrar em espera caso não tenham um runnable para processar. A grande vantagem é que entre um runnable e outro não há a destruição e nem a criação de threads, o que consome muito desempenho. Ele também tem a vantagem de permitir que você regule o número máximo de threads.

Um thread pool é criado da seguinte forma:

//Cria um pool de 50 threads para suas requisições ExecutorService requisitionPool = Executors.newFixedThreadPool(50);

O objeto requisitionPool terá um método para submeter um Runnable ou um Future a uma das suas threads. Esse método bloqueia se não houver threads disponíveis para atender a essa solicitação. A sua classe que controla esse pool pode então enfileirar as mensagens recebidas e se utilizar das 50 threads do pool para envia-las.

Ter threads demais no computador também é um problema, pois cada thread diminui a eficiência do sistema operacional como um todo. Ela exige que o SO faça trocas de contexto, o que pode ser prejudicial quando o número de threads é muito grande.

J

O pool de threads eu já faço deesta maneira.
Crio um pool e cada thread faz suas próprias requisições, o que eu queria saber mesmo era se tem como acelerar o envio das mensgens por socket.
Para criar o pool eu uso java.util.concurrent.* e para fazer as requisições socket eu uso java.net.Socket.
Estava dando uma pesquisada e via algo sobre java.nio.channels.SocketChannel, alguém já usou é mais rápido que a classe Socket?

T

Se a aplicação deve atender um número excessivo de requisições simultâneas e precisa usar Java NIO e você é um pouco masoquista, pode tentar usar o Apache Mina:
http://mina.apache.org/

V

Eu já usei. É sim mais rápido. Especialmente se você usar os Selectors.
Nesse caso, pode até poupar muitas das threads que manipulam o socket.

Agora, você pode ter problemas com socket por outras causas, como a aplicação que recebe os dados não estar sendo capaz de trata-los. Isso faz com que a janela de envio do socket fique cheia, e acabe também interrompendo o servidor.

Se a aplicação que recebe enfileira mensagens na memória, sem um limite, você pode cair num ciclo prejudicial na sua aplicação:

  1. Sua aplicação não é capaz de processar, o buffer de memória dela vai enchendo;
  2. O buffer fica cheio, a aplicação fica mais lenta, e menos capaz de processar;
  3. Estando menos capaz de processar o buffer enche mais e mais rápido…

É bom testar essa situação também.

V

Uma coisa…

Você já rodou um profiler na sua aplicação, tanto na que envia quanto na que recebe, e procurou por gargalos de software? Já mediu a taxa de transferência na sua rede com o wireshark?

Acho que antes de alterar sua arquitetura, e tentar otimizar o socket, é bom ter certeza de que esse é o gargalo de performance!

J

A minha aplicação funciona como cliente.
Eu envio dados via GET para um servidor em uma outra máquina.
A aplicação funciona da seguinte maneira, ela vai no banco de dados pega as informações necessárias, monta uma url http e envia para uma determinada máquina. Sendo que este envio podem ser simultâneamente para várias máquinas, porque o usuário pode configurar vários serviços, que para a aplicação são máquinas de destinos.
As máquinas que vão receber estas requisições são servidores apaches com php.
Eu poderia ter muitos problemas com o SocketChannel, neste ambiente?

V

Eu acho que não…

Mas antes de começar a otimizar, meça e tenha certeza… use o profiler.

J

Fiz mais algumas pesquisas e gostaria de saber se vocês já usaram HttpComponents? É um projeto do jakarta.

V

Já consegui um throughput de 6mB/s usando sockets.
Qual é o seu throughput?

J

Desculpa a minha ignorância…hehehe
O que é throughput?

V

É a “vazão” que vc consegue imprimir num canal…
No caso, a taxa de transferência máxima.

L

ola deonde é este:

ExecutorService requisitionPool = Executors.newFixedThreadPool(50);

como ele funciona?
como é este esquema de pool de threads?

J

Entendi, valeu pela explicação.
No meu caso os dados são pequenos são apenas alguns parâmetros na url.

Vai no site http://java.sun.com/javase/6/docs/api/ e entra no pacote java.util.concurrent, lá vai ter tudo o que você precisa para criar um pool de threads.

J

Mais uma coisa este SocketChannel ele cria um pool? ou Eu tenho que fazer várias threads com um SocketChannel? Ou seria um tipo de “gerenciador de conexões”?

V

Não, com os selectors você não precisaria criar várias threads.
Eles permitam que você saiba exatamente quando há dados em cada canal de comunicação, e então a thread pode fazer a leitura sem bloquear.

Eu ainda acho que o problema não é a classe Socket.
E há altas chances de você está gastando seu tempo e esforço no local errado…

L

Ola sabe onde tenha algum exemplo de chat com java???
e um sistema de um jogo online?
neste caso alem do servidor o cliente teria varias threads dos outros jogadores tbm não e?
sabe onde tenha um material um exemplo ou algo referente a estas coisas?

V

Por sinal, tenho. Eu fiz recentemente para os meus alunos de fundamentos.

Aqui tem um exemplo de um chat mega-super-ultra-duper simples em TCP e um não tão simples assim em UDP.
No caso do UDP, tem também um aplicativo que é um pequeno túnel, que te permite inserir erros comuns, tal como atrasos, jitter, erros, etc.

A idéia do tunel é poder simular condições ruins de rede, comuns no caso de jogos. O TCP é uma péssima opção para os jogos porque ele intensifica o lag da rede, já que faz retransmissão.

Estou fazendo um pong multiplayer para a pós. Assim que eu terminar, eu publico no meu site.

L

valeu… o sobre as portas quais devem ser usadas para um chat?

V

Quais você quiser. O ideal é não usar uma das Well Known Ports.

Eu geralmente uso 15980, já que 15/09/80 é a data do meu nascimento. :smiley:

L

no simplechat to tentando conectar mas não obtive sucesso ele fica travado no “Aguardando conexao…”
no

Socket s = socket.accept();

qdo tento iniciar o servidor…

V

Sim… vc então deve abrir outro chat e conectar nele.

Use, por exemplo, os parâmetros
-server 15980
(abre o server na porta 15980)

Rode de novo e:
-client 127.0.0.1 15980
(conecta o client nesse server).

J

ViniGodoy:
Algumas dicas:

  1. O cliente não terá mais de uma thread. Só o server.
  2. O servidor terá 1 thread para esperar os clientes (método accept) e uma thread para cada cliente criado;
  3. Cada cliente que for criado deve ser colocado num List. Assim, quando uma mensagem chegar, você pode redistribuir para os outros clientes;
  4. Não utilize o ObjectOutputStream, no lugar, pense no DataOuputStream. Por lá tem um método readUTF, que deve ser mais fácil de usar no seu caso.

Mano, mto boa dica!!

Vai ser mto util…

TkssS

H

ViniGodoy:
Algumas dicas:

  1. O cliente não terá mais de uma thread. Só o server.
  2. O servidor terá 1 thread para esperar os clientes (método accept) e uma thread para cada cliente criado;
  3. Cada cliente que for criado deve ser colocado num List. Assim, quando uma mensagem chegar, você pode redistribuir para os outros clientes;
  4. Não utilize o ObjectOutputStream, no lugar, pense no DataOuputStream. Por lá tem um método readUTF, que deve ser mais fácil de usar no seu caso.

Andei lendo varios e varios topicos mais acabei num achando. Estou fazendo um trabalho pa facul igual a esse, utilizei a dica de topico pra fazer, mais depois acabei achando um erro. Crio a thread pro novo client, ele muda as portas e tals, até ai ta blz, qdo o client envia uma msg as info criada qdo ele conectou não estão disponiveis. Tipo criei 4 vetores, users, ips, ports, salas qdo vou acessar esses dados eles estão apenas na primeira thread. Tem como eu acessar esses dados? Caso num fui claro postem oke não entenderam.

Obrigado pela atenção.

T

Desculpem a resurreição do tópico.

Vini, você por acaso terminou o Pong?

Por acaso, eu fiz um pra disciplina de Sistemas Distribuídos na faculdade, mas não implementei toda a lógica do jogo porque tive pouco tempo. O professor aceitou assim mesmo, uma vez que a parte de rede está 100% funcional.

Segue em anexo o arquivo do projeto, bastando descompactar e abrir no Eclipse.

EDIT - nossa… essa versão do fonte tá sem nenhum comentário… Vou procurar a versão mais recente e depois substituo esse anexo.

V

Terminei sim. O servidor suporta 3 jogos de Pong simultâneos. Trabalhei com UDP.

Mas não gostei do resultado. O Pong é o pior caso possível para um jogo em rede. Tentei implementar Dead Reckoning, mas o jogo é deterministico demais e exige uma resposta imediata demais para que possamos disfarçar o lag de rede.

M

marceloplis:
Veja se isso te ajuda:

http://www.guj.com.br/java.tutorial.artigo.20.1.guj

Gostei deste tutorial! Só que lá diz que dá pra baixar os arquivos fontes mas eu não achei o link!! Será que estou cego?? :cry:

M

Olá será que alguém poderia me ajudar estou criando um chat onde o usuario pode escolher se vai mandar a mensagem para todos os usuarios ou uma mensagem privada para apenas um usuário, se ele escolher apenas um é aberta uma nova janela para digitar sua mensagem mais não estou conseguindo fazer esse mensagem chegar apenas para o determinado destinatário ela está indo para todos.
Alguém sabe o que posso fazer
Obrigado

meu email para contato é :
[email removido]

V

Há duas formas de fazer isso:

  1. A mais eficiente e segura, porém mais difícil: É usar uma forma de endereçamento que o servidor reconheça. Por exemplo, o nome da pessoa ou o endereço da máquina, ou ainda algum ID negociado. Acho que eu usaria a última forma. Então, adicione ao seu protocolo o ID de quem deve receber a mensagem e faça com que o servidor só envie a mensagem para essa pessoa. Uma forma fácil de se obter isso é ter no servidor um mapa, que liga o id ao Socket que tem aquele id.

  2. A forma menos eficiente, menos segura, porém mais fácil. Adicione um identificador na mensagem e faça com que o cliente que recebe as mensagens simplesmente ignore mensagens sem aquele identificador. É menos eficiente pois o servidor ainda irá repassar mensagens para clientes que não irão lê-las, o que é um desperdício de banda. E é mais insegura pois alguém mal intencionado poderia criar um cliente capaz de ler mensagens privadas dos outros, já que elas efetivamente chegam.

C

Boa tarde Galera !!! o meu chat ta mandando mensagem pra todos,mas eu precisava mandar pra somente um destinatario tambem, gostaria de saber como faço isso,se alguem puder me ajudar desde ja grato pela força flw galera abraço t+.segue abaixo o código.

C
cassiojoselito:
Boa tarde Galera !!! o meu chat ta mandando mensagem pra todos,mas eu precisava mandar pra somente um destinatario tambem, gostaria de saber como faço isso,se alguem puder me ajudar desde ja grato pela força flw galera abraço t+.segue abaixo o código.
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Servidor {
     
	public static void main(String [] args) throws IOException {
               
    	 //inicia o servidor
    	 
    	 new Servidor(12345).executa();
     }
     
     private int porta;
     private boolean encerrar;
     
     private List<PrintStream> clientes;
     
     public Servidor (int porta) {
    	 this.porta = porta;
    	 this.clientes = new ArrayList<PrintStream>();
     }
     public void executa () throws IOException {
    	 
    	 ServerSocket servidor = new ServerSocket(this.porta);
    	 
    	 System.out.println("Porta 12345 aberta!");
    	 
    	 while (!encerrar){
    		 
    		 //aceita um cliente
    		 
    		 Socket cliente = servidor.accept();
    		 System.out.println("Nova conexao com o cliente" +
    				 cliente.getInetAddress().getHostAddress());
    		 
    		 //adiciona saida do cliente à lista
    		 
    		 PrintStream ps = new PrintStream(cliente.getOutputStream());
    		 this.clientes.add(ps);
    		 
    		 //cria tratador de cliente numa nova tread
    		 
    		 TrataCliente tc = new TrataCliente(cliente.getInputStream(),this);
    		 new Thread(tc).start();}
    	 
    	 }
     public void distribuiMensagem(String msg) {
    	
    	 // envia msg para um só destinatario
    	 
    	 for (PrintStream cliente : this.clientes) 
    	 cliente.println(msg);
    	 
     }
    	 
     public class TrataCliente implements Runnable {
	   
	   private InputStream cliente;
	   private Servidor servidor;
	
	   public TrataCliente(InputStream cliente,Servidor servidor){
	   
	   this.cliente = cliente;
	   this.servidor = servidor;
	 }
   
	   public void run() {
	   
	   //quando chegar uma msg distribui pra todos
	   
	   Scanner s = new Scanner(this.cliente);
    	 
	   while (s.hasNextLine()) {
    		 servidor.distribuiMensagem(s.nextLine());
    		 }
    	 s.close();
   }
   }
}
C

é esse codigo ai desculpa mandei o codigo errado

V

A resposta pra sua dúvida está exatamente em cima da sua pergunta.

C

Cara,mapear o servidor seria fazer com que ele saiba quem esta conectado nele ? e quando eu mandar uma menssagem para um determinado cliente ou pessoa ele reconheça essa pessoa na lista de clientes e entregue esa mensagem a essa pessoa ? mas os clientes ja estão numa lista todos conectados,como saber que tal cliente esta em tal posição da lista,ou em tal index da lista ? como indentificar um usuario na lista ? a lista guarda que informação do usuario ? o ip ?acho que não é o ip, deve ter uma especie de id auto increment pois ela guarda usuarios com o mesmo ip caso estejamos executando o chat na mesma maquina de começo acho que eu deveria imprimir uma lista de todos os clientes conectados com o seu respectivo index e apelido por exemplo no qual eu vou de começo digitar o index do destinatario.Como faço para pegar o index da lista ? Se tiver algum material pra indicar pra eu dar uma olhada desde ja grato abraço Cara

V

Você tem que elaborar um protocolo:
http://www.guj.com.br/posts/list/136538.java#735860

Depois disso, crie um Map no seu servidor, que relaciona uma conexão socket cliente à um ID. Se você está fazendo um servidor de chat, você pode usar como ID o próprio nick de quem está naquela conexão, desde que o servidor recuse duas conexões com o mesmo id. O seu protocolo também terá que conter mensagens de “fulano entrou”, “fulano saiu”, etc.

C
Ai Galera, boa tarde ,esquecendo um pouco a parte de enviar mensagem somente para um cliente.Eu achei um exemplo na net com formulario e tudo, pois tava osso de implementar os forms,o exemplo ta prontinho com form e tudo porem existe somente um cliente e servidor e o cliente manda mensagem para o servidor.tentei fazer com que exista mais de um cliente e que ele faça um broadcast(mande uma mensagem enviada por um cliente para todos os clientes).TA DANDO ERRO NO METODO MAIN DO SERVIDOR E NO PROTECT VOID FINALIZE.segue o codigo se alguem puder dizer onde eu estou errando desde ja GRATO
public class socketcliente extends JFrame implements ActionListener {
	 /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	JLabel text,clicked;
     JButton botao;
     JPanel painel;
     JTextField campotexto;
     Socket socket = null;
     PrintWriter saida = null;
     BufferedReader entrada = null;
     
     socketcliente() //iniciamos o constructor
     {
             text = new JLabel("Texto a enviar por socket:");
             campotexto= new JTextField(30);
             botao = new JButton("Enviar!");
             botao.addActionListener(this);
             
             painel = new JPanel();
             painel.setLayout(new BorderLayout());
             painel.setBackground(Color.white);
             getContentPane().add(painel);
             painel.add("North", text);
             painel.add("Center", campotexto);
             painel.add("South", botao);
     }
     @Override
     public void actionPerformed(ActionEvent event) 
     {
             Object fonte = event.getSource();
             
             if (fonte == botao) //Envia informacao pelo socket
             {
                     String text = campotexto.getText();
                     saida.println(text);
                     campotexto.setText(new String("")); //recebe do servidor
                     
                     try{
                             String linha = entrada.readLine();
                             System.out.println("Texto recebido: " + linha);
                     }
                     catch (IOException e)
                     {
                             System.out.println("Falha na leitura!");
                             System.exit(1);
                     }
             }
     }
     
     public void EscutaSocket() //cria ligacao de socket
     {
    	 class Recebedor implements Runnable {
    		 
    		  private InputStream servidor;
    		 
    		  public Recebedor(InputStream servidor) {
    		  this.servidor = servidor;
    		  }

			@Override
			public void run() {
				// recebe msgs do servidor e imprime na tela
				 Scanner s = new Scanner(this.servidor);
				 while (s.hasNextLine()) {
				System.out.println(s.nextLine());
				}
				 
				
			}
    	 }
    	 try
             {
                     Socket cliente = new Socket("127.0.0.1", 85); //aqui decidimos qual o IP e a sua porta, neste caso 127.0.0.1:85
                     saida = new PrintWriter(cliente.getOutputStream(), true);
                     entrada = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
                     
                     //thread para receber mensagens do servidor
                      Recebedor r = new Recebedor(cliente.getInputStream());
                      new Thread(r).start();
                      
                   // le msgs do teclado e manda pro servidor
                      Scanner teclado = new Scanner(System.in);
                      PrintStream saida = new PrintStream(cliente.getOutputStream());
                      while (teclado.hasNextLine()) {
                      saida.println(teclado.nextLine());
                       }
                     
             }
             catch(UnknownHostException e)
             {
                     System.out.println("Host desconhecido: localhost");
                     System.exit(1);
             }
             catch (IOException e)
             {
                     System.out.println("Não Existe Entrada nem Saída de informação");
                     System.exit(1);
                     }
             }
        public static void main(String[] args) {
		socketcliente frame = new socketcliente();
        frame.setTitle("Cliente");
        WindowListener ls = new WindowAdapter()
        {
                public void windowClosing(WindowEvent e)
                {
                        System.exit(0);
                }
        };
        frame.addWindowListener(ls);
        frame.pack();
        frame.setVisible(true);
        frame.EscutaSocket();
}
}
public class SocketServidor extends JFrame implements ActionListener {
	 /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	JButton botao;
	   JLabel label = new JLabel("Texto Recebido:");
	   JPanel painel;
	   JTextArea campotexto = new JTextArea();
	   ServerSocket servidor = null;
	   Socket cliente = null;
	   BufferedReader entrada = null;
	   PrintWriter saida = null;
	   String linha;

	   SocketServidor(){ //Constructor
	     botao = new JButton("Receber!");
	     botao.addActionListener(this);

	     painel = new JPanel();
	     painel.setLayout(new BorderLayout());
	     painel.setBackground(Color.white);
	     getContentPane().add(painel);
	     painel.add("North", label);
	     painel.add("Center", campotexto);
	     painel.add("South", botao);

	   } 
      private boolean encerrar;
      private List<PrintStream> clientes;
	  public void actionPerformed(ActionEvent event) 
	       {
	       Object source = event.getSource();

	     if(source == botao)
	       {
	         campotexto.setText(linha);
	       }
	       }
	     public void EscutaSocket() throws IOException{

	    try{
	      servidor = new ServerSocket(85); //Definição da porta que vai ficar à escuta, neste caso : porta 85
	    } catch (IOException e) {
	      System.out.println("Não é possivel escutar na porta 85");
	      System.exit(-1);
	    }
	    try{
	        cliente = servidor.accept();
	      } catch (IOException e) {
	        System.out.println("Servidor não aceitou: 85"); //
	        System.exit(-1);
	      }
	      try{
		      entrada = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
		      saida = new PrintWriter(cliente.getOutputStream(), true);
		    } catch (IOException e) {
		      System.out.println("Falha de permissão: 85");
		      System.exit(-1);
		    }
		 
		    while(true){
		      try{
		        linha = entrada.readLine();
		//Send data back to cliente
		        saida.println(linha);
		      } catch (IOException e) {
		        System.out.println("Falha de Leitura!");
		        System.exit(-1);
		      }
		    }
		    protected void finalize()
			  {
			//Clean up 
			     try{
			        entrada.close();
			        saida.close();
			        servidor.close();
			    } catch (IOException e) {
			        System.out.println("Não é possivel fechar!.");
			        System.exit(-1);
			    }
			  }
		    public static void main(String[] args) throws IOException {
				SocketServidor frame = new SocketServidor();
		        frame.setTitle("Servidor");
		        WindowListener ls = new WindowAdapter() {
		                public void windowClosing(WindowEvent e) {
		                        System.exit(0);
		                }
		        };
		        frame.addWindowListener(ls);
		        frame.pack();
		        frame.setVisible(true);
		        frame.EscutaSocket();
			}
	     
	    while (!encerrar) {
	    	 // aceita um cliente
	    	 Socket cliente = servidor.accept();
	    	 System.out.println("Nova conexão com o cliente " +
	    	 cliente.getInetAddress().getHostAddress()
	    	 );
	    //try{
	      //cliente = servidor.accept();
	  
	      // adiciona saida do cliente à lista
	      
	      PrintStream ps = new PrintStream(cliente.getOutputStream());
	     this.clientes.add(ps);
	     
	       // cria tratador de cliente numa nova thread
	     
	     TrataCliente tc = new TrataCliente(cliente.getInputStream(), this);
	     new Thread().start();}}

	    
	     public void distribuiMensagem(String msg) {
	 		// envia msg para todo mundo
	 		   for (PrintStream cliente1 : this.clientes) {
	 		   cliente1.println(msg);
	 		  }
	 		   }
	     class TrataCliente implements Runnable {
		    	
		    	private InputStream cliente;
		    	 private SocketServidor servidor;
		    	
		    	 public TrataCliente(InputStream cliente, SocketServidor servidor) {
		    	this.cliente = cliente;
		    	 this.servidor = servidor;
		    	 }
               public void run() {
					// quando chegar uma msg, distribui pra todos
					 Scanner s = new Scanner(this.cliente);
					
					while (s.hasNextLine()) {
					servidor.distribuiMensagem(s.nextLine());
					}
					s.close();
					}
	     }	
			
}
V

Seria muito interessante você dizer que erro tá dando, especialmente se você ainda destacar a linha que o erro acusa.

C

Então ta dando esse erro na linha 84 da classe SocketServidor(a segunda classe)

Multiple markers at this line
- Syntax error, insert “;” to complete
LocalVariableDeclarationStatement
- Syntax error on token “(”, ; expected

E ta dando esse erro aqui na linha 72 da mesma classe SocketServidor

Multiple markers at this line
- Syntax error on token “void”, @ expected
- Syntax error, insert “enum Identifier” to complete
EnumHeaderName

V

Esses erros geralmente acontecem quando você:

a) Esquece de fechar chaves (ou fecha chaves demais);
b) Esquece de fechar parênteses ou aspas;

Não sei se era sua intenção, mas o método finalize() é usado pelo garbage collector, e você ali está fazendo uma sobrecarga.
Você queria isso mesmo?

Outra coisa… essas linhas se referem ao código que vc postou aqui no GUJ? Digo, se eu olhar o seu post lá atrás, vou ver a mesma linha que está acusando na IDE aí?

C

Ai Galera

C

cassiojoselito:
Valeu pela dica, retirei o finalize, e agora ta sem errro,mas como juntei um código que tava com formulario e tinha um cliente que mandava mensagem para um servidor com um exemplo que não tinha formularios porem tinha varios clientes que podiam mandar broadcast para todos os clientes passando pelo servidor meu código agora que segue abaixo abre o formulario do servidor abre mais de um formulario de cliente mas não se comunica,se alguem puder me dar uma dica dizendo onde estou errando,desde ja grato.Abraço

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*; // pacote de streams
import java.net.*; // pacote de sockets
import java.util.Scanner;

public class socketcliente extends JFrame implements ActionListener {
	 private static final long serialVersionUID = 1L;
	 JLabel text,clicked;
     JButton botao;
     JPanel painel;
     JTextField campotexto;
     Socket socket = null;
     PrintWriter saida = null;
     BufferedReader entrada = null;
     
     socketcliente(){ //iniciamos o constructor
          text = new JLabel("Texto a enviar por socket:");
          campotexto= new JTextField(30);
          botao = new JButton("Enviar!");
          botao.addActionListener(this);
          painel = new JPanel();
          painel.setLayout(new BorderLayout());
          painel.setBackground(Color.white);
          getContentPane().add(painel);
          painel.add("North", text);
          painel.add("Center", campotexto);
          painel.add("South", botao);
     }
    public void actionPerformed(ActionEvent event) 
         {
          Object fonte = event.getSource();
                if (fonte == botao) //Envia informacao pelo socket
                     {
                         String text = campotexto.getText();
                         saida.println(text);
                         campotexto.setText(new String("")); //recebe do servidor
                         try{
                             String linha = entrada.readLine();
                             System.out.println("Texto recebido: " + linha);
                            }
                         catch (IOException e)
                             {
                               System.out.println("Falha na leitura!");
                               System.exit(1);
                             }
                    }
        }
     public void EscutaSocket() //cria ligacao de socket
          {
    	    class Recebedor implements Runnable {
    		    private InputStream servidor;
    		    public Recebedor(InputStream servidor) {
    		         this.servidor = servidor;
    		    }
                public void run() {
				     // recebe msgs do servidor e imprime na tela
				     Scanner s = new Scanner(this.servidor);
				     while (s.hasNextLine()) {
				     System.out.println(s.nextLine());
				                              }
				                  }
    	                                         }
    	  try
             {
                Socket cliente = new Socket("127.0.0.1", 85); //aqui decidimos qual o IP e a sua porta, neste caso 127.0.0.1:85
                saida = new PrintWriter(cliente.getOutputStream(), true);
                entrada = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
                //thread para receber mensagens do servidor
                Recebedor r = new Recebedor(cliente.getInputStream());
                new Thread(r).start();
                // le msgs do teclado e manda pro servidor
                Scanner teclado = new Scanner(System.in);
                PrintStream saida = new PrintStream(cliente.getOutputStream());
                while (teclado.hasNextLine()) {
                	saida.println(teclado.nextLine());
                                              }
              }
             catch(UnknownHostException e)
                 {
                     System.out.println("Host desconhecido: localhost");
                     System.exit(1);
                 }
             catch (IOException e)
             {
                     System.out.println("Não Existe Entrada nem Saída de informação");
                     System.exit(1);
                     }
             }
     public static void main(String[] args) {
		  socketcliente frame = new socketcliente();
		  frame.setTitle("Cliente");
		  WindowListener ls = new WindowAdapter(){
                public void windowClosing(WindowEvent e)
                {
                        System.exit(0);
                }
                                                  };
          frame.addWindowListener(ls);
          frame.pack();
          frame.setVisible(true);
          frame.EscutaSocket();
}
}
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.List;

public class SocketServidor extends JFrame implements ActionListener {
	 private static final long serialVersionUID = 1L;
	       JButton botao;
	       JLabel label = new JLabel("Texto Recebido:");
	       JPanel painel;
	       JTextArea campotexto = new JTextArea();
	       ServerSocket servidor = null;
	       Socket cliente = null;
	       BufferedReader entrada = null;
	       PrintWriter saida = null;
	       String linha;

	 SocketServidor(){ //Constructor
		  botao = new JButton("Receber!");
	      botao.addActionListener(this);
          painel = new JPanel();
	      painel.setLayout(new BorderLayout());
	      painel.setBackground(Color.white);
	      getContentPane().add(painel);
	      painel.add("North", label);
	      painel.add("Center", campotexto);
	      painel.add("South", botao);
         } 
     private boolean encerrar;
     private List<PrintStream> clientes;
	 public void actionPerformed(ActionEvent event){
	       Object source = event.getSource();
          if(source == botao)
	       {
	         campotexto.setText(linha);
	       }
	       }
	 public void EscutaSocket() throws IOException{
        try{
	      servidor = new ServerSocket(85); //Definição da porta que vai ficar à escuta, neste caso : porta 85
	      while (!encerrar) {
		      // aceita um cliente
		      Socket cliente = servidor.accept();
		      System.out.println("Nova conexão com o cliente " +
		      cliente.getInetAddress().getHostAddress()
		    	 );
		    
		      //cliente = servidor.accept();
		  
		      // adiciona saida do cliente à lista
		      
		      PrintStream ps = new PrintStream(cliente.getOutputStream());
		      this.clientes.add(ps);
		     
		       // cria tratador de cliente numa nova thread
		     
		     new Thread().start();}
	    } catch (IOException e) {
	      System.out.println("Não é possivel escutar na porta 85");
	      System.exit(-1);
	    }
	    try{
	        cliente = servidor.accept();
	      } catch (IOException e) {
	        System.out.println("Servidor não aceitou: 85"); //
	        System.exit(-1);
	    }
	    try{
		    entrada = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
		    saida = new PrintWriter(cliente.getOutputStream(), true);
		    } catch (IOException e) {
		      System.out.println("Falha de permissão: 85");
		      System.exit(-1);
		    }
		 while(true){
		      try{
		        linha = entrada.readLine();
		//Send data back to cliente
		        saida.println(linha);
		      } catch (IOException e) {
		        System.out.println("Falha de Leitura!");
		        System.exit(-1);
		      }
		    }
		   }
		 public void distribuiMensagem(String msg) {
		      // envia msg para todo mundo
		 	  for (PrintStream cliente : this.clientes) {
		 		  cliente.println(msg);
		 		  }
		 		   }
		 public static void main(String[] args) throws IOException {
			  SocketServidor frame = new SocketServidor();
		      frame.setTitle("Servidor");
		      WindowListener ls = new WindowAdapter() {
		            public void windowClosing(WindowEvent e) {
		                    System.exit(0);
		                }
		        };
		      frame.addWindowListener(ls);
		      frame.pack();
		      frame.setVisible(true);
		      frame.EscutaSocket();
		    }
}

V

Não entendi nada. Talvez essas dicas possam te ajudar.

C

Então cara acontece o seguinte: ja dei um arrumada no código lá, tirando o finalize e acertei os devidos parênteses, agora o código que ta sem erro de sintaxe, esta criando os formularios dos clientes e do servidor, porem não comunicam-se.O que tentei fazer nesse codigo é juntar 2 aplicações que eu tinha como exemplo de sockets, uma que tinha um cliente comunicando-se com o servidor com os seus respectivos formulario, e outra sem formularios, que tinha varios clientes que mandavam mensagens uns aos outros atravez de multcast, ou seja um cliente não se comunicava somente com outro cliente, mas sim mandava uma mensagem para todos os outros clientes.O que to tentando fazer no código acima é fazer um multcast com formularios em que o cliente manda mensagem aos outros passando pelo servidor,desde ja grato, Abraço

U

Não entendi nada. Talvez essas dicas possam te ajudar.

haha boa!

M

Não sei se ajuda, mas to mandando um link com um chat que fiz. Está simples, devido ao curto intervalo de tempo para fazer.
O anexo contém o programa e um artigo. vlw.

http://sites.google.com/site/diogooliveiramonte/trabalhos-e-artigos

C

ola a todos!
gostaria se for possível alguém dar.me uma ajudinha!
estou a fazer um chat em java utilizando JRMI
e estou com alguns problemas!
por exemplo quando um novo cliente entre, o primeiro que peço é que introduza um nick,
então eu mando isso para o servidor e ele vai verificar se existe, se existir tem de pedir novamente o nick, como faço isto para que sempre este a pedir o nick caso já exista um registado?
tive a tentar implementar algo do tipo um while (c.registo(nick)) que vai pedir o nick e enviar po servidor ate que nao seja verificado a condiçao! mas não estou a conseguir!
alguém poderia dar alguma dica?

muito obrigado a todos!

T

Preciso de uma ajuda criei uma Chat mas não tenho uma ideia de como posso fazer para gerencia-lo corretamente, pois preciso deixar que os usuarios possam criar as salas e é esse o meu problema.

V

ViniGodoy:
Algumas dicas:

  1. O cliente não terá mais de uma thread. Só o server.
  2. O servidor terá 1 thread para esperar os clientes (método accept) e uma thread para cada cliente criado;
  3. Cada cliente que for criado deve ser colocado num List. Assim, quando uma mensagem chegar, você pode redistribuir para os outros clientes;
  4. Não utilize o ObjectOutputStream, no lugar, pense no DataOuputStream. Por lá tem um método readUTF, que deve ser mais fácil de usar no seu caso.

Viny

Em outro post do forum , copiei um arquivo de simpleChat que disponibilizou , estou com uma dúvida nesse trecho de código.

private void talk(OutputStream outputStream) throws IOException{
		DataOutputStream output = new DataOutputStream(outputStream);
		String line = "";
		
		while (!line.equals("EXIT")){
			
			Scanner scan = new Scanner(System.in);        
			System.out.print(": ");
			line = scan.nextLine();
			output.writeInt(line.length());
			
			for (char ch : line.toCharArray())
				output.writeChar(ch);
				output.flush();
		}
	}

Gostaria de saber primeiramente por quê envia a linha output.writeInt(line.length()); e somente depois percorre a String line , enviando char por char ?
ao invés de usar o método writeChars(String s) DataOutputStream ?
Obrigado !

V

Porque a idéia desse código é demonstrar como se montar um protocolo de comunicação. Você irá fazer desse jeito para outros tipos de bytes, como envio de arquivos, imagens, etc.

V

ok Viny , obrigado !

V

Esse código eu montei em aula, com os alunos. Primeiro desenhamos um protocolo, e eu fui explicando os desafios de enviar e receber dados. Por que você precisa de tamanhos, como o socket funciona, como funcionam os reads e os writes. Depois programamos isso na frente da turma. E depois passei de lição para que eles adicionassem troca de arquivos no protocolo.

Foi muito interessante, a turma gostou muito. Geralmente eles gostam de ver professores “colocando a mão na massa”.

V

ViniGodoy:
Esse código eu montei em aula, com os alunos. Primeiro desenhamos um protocolo, e eu fui explicando os desafios de enviar e receber dados. Por que você precisa de tamanhos, como o socket funciona, como funcionam os reads e os writes. Depois programamos isso na frente da turma. E depois passei de lição para que eles adicionassem troca de arquivos no protocolo.

Foi muito interessante, a turma gostou muito. Geralmente eles gostam de ver professores “colocando a mão na massa”.

modifiquei seu código fazendo ele comunicar com outro cliente ao invés de cliente servidor , se quiser verificar o código posso postar aqui , para poder indicar os pontos fracos do meu código.

L

Preciso de ajuda para fazer retornar as mensagens agora aos clientes. Dei uma repaginada em todo o fonte para funcionar melhor.
São tres classes responsáveis por isso listadas abaixo.

ChatServer

import java.io.IOException;
import java.net.ServerSocket;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ChatServer implements Runnable {
	
	private static final int PORTA = 45054;
	private static List&lt;Usuario&gt; lista = new ArrayList&lt;Usuario&gt;();
	private Usuario cliente;

	public ChatServer(Usuario cliente) {
		this.cliente = cliente;
	}

	@Override
	public void run() {
		try {
			DateFormat dateFormat = DateFormat.getDateTimeInstance();
			System.out.println("["+dateFormat.format(new Date())+"] Atendendo Cliente ("+cliente.getIp()+").");
			String msg;
			do{
				cliente.setNome(cliente.getEntrada().readLine());
				msg = cliente.getEntrada().readLine();
				//entrada.close();
				if(!msg.equals("Sair")){
					System.out.println(cliente.getNome()+" disse: "+msg);
					if(!msg.isEmpty()){
						for (Usuario usuarioLogado : lista) {
							usuarioLogado.getSaida().write(msg);
							usuarioLogado.getSaida().newLine();
							usuarioLogado.getSaida().flush();
						}
					}
				}else{
					System.out.println("["+dateFormat.format(new Date())+"] Cliente ("+cliente.getIp()+") desconectado.");
					cliente.disconnect();
					atualizaLista();
				}
			}while(!msg.equals("Sair"));
		} catch (IOException e) {
			System.err.println("Erro: "+e.getMessage());
			System.exit(-1);
		}
	}

	private void atualizaLista() {
		for (int i=0; i&lt;lista.size(); i++) {
			if(lista.get(i).getConexao().isClosed()){
				lista.remove(i);
				i--;
			}
		}
	}

	public static void main(String[] args) {
		try {
			DateFormat dateFormat = DateFormat.getDateTimeInstance();
			System.out.println("["+dateFormat.format(new Date())+"] Inicializando Servidor de chat.");
			ServerSocket servidor = new ServerSocket(PORTA);
			System.out.println("["+dateFormat.format(new Date())+"] Servidor de chat executando na porta "+PORTA+".");
			System.out.println("["+dateFormat.format(new Date())+"] Aguardando conexões de Clientes.");
			while(true){
				Usuario cliente = new Usuario(servidor.accept());
				System.out.println("["+dateFormat.format(new Date())+"] Conexão aceita de Cliente ("+cliente.getIp()+").");
				lista.add(cliente);
				new ChatServer(cliente).run();
			}
		} catch (IOException e) {
			System.err.println("Erro: "+e.getMessage());
			System.exit(-1);
		}
		
	}
}

ChatClient

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.util.Date;
import java.util.Scanner;

public class ChatClient implements Runnable {
	
	private static final int PORTA = 45054;
	private Usuario cliente;

	public ChatClient(Usuario cliente2) {
		this.cliente = cliente2;
	}

	@Override
	public void run() {
		try {
			String msg;
			do{
				msg = cliente.getEntrada().readLine();
				if(!msg.equals("Sair")){
					System.out.println(cliente.getNome()+" disse: "+msg);
				}
			}while(!msg.equals("Sair"));
			cliente.disconnect();
		} catch (IOException e) {
				System.err.println("Erro: "+e.getMessage());
				System.exit(-1);
		}
	}

	public static void main(String[] args) {
		if(args.length==0 || args[0].length()==0 || args[1].length()==0){
			System.out.println("Uso incorreto. Tente:\n\t" +
					"java ChatCliente &gt;&lt;ip ou hostname&gt; &lt;nome de usuario&gt;");
			System.exit(-1);
		}
		try {
			Scanner scan = new Scanner(System.in);
			DateFormat dateFormat = DateFormat.getDateTimeInstance();
			System.out.println("&lt;"+dateFormat.format(new Date())+"&gt; Conectando ao Servidor de chat.");
			Usuario cliente = new Usuario(new Socket(args[0], PORTA));
			cliente.setNome(args[1]);
			System.out.println("&lt;"+dateFormat.format(new Date())+"&gt; Iniciando serviço de mensagens.");
			//new ChatClient(cliente).run();
			System.out.println("&lt;"+dateFormat.format(new Date())+"&gt; Pronto para envio e recebimento de mensagens.");
			System.out.println("Digite uma mensagem e pressione enter para enviá-la ou digite 'Sair' para desconectar.");
			String msg;
			do{
				msg = scan.nextLine();
				cliente.getSaida().write(cliente.getNome());
				cliente.getSaida().newLine();
				cliente.getSaida().write(msg);
				cliente.getSaida().newLine();
				cliente.getSaida().flush();
			}while (!msg.equals("Sair"));
			System.out.println("&lt;"+dateFormat.format(new Date())+"&gt; Cliente se desconectou do Servidor de chat.");
			cliente.disconnect();
		} catch (UnknownHostException e) {
			System.err.println("Erro: "+e.getMessage());
			System.exit(-1);
		} catch (IOException e) {
			System.err.println("Erro: "+e.getMessage());
			System.exit(-1);
		}
	}

}

Usuario

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Usuario {
	private String nome;
	private Socket conexao;
	private BufferedReader entrada;
	private BufferedWriter saida;
	
	public Usuario(Socket conexao) throws IOException {
		super();
		this.conexao = conexao;
		this.entrada = new BufferedReader(new InputStreamReader(conexao.getInputStream()));
		this.saida = new BufferedWriter(new OutputStreamWriter(conexao.getOutputStream()));
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Socket getConexao() {
		return conexao;
	}
	
	public String getIp(){
		return conexao.getLocalAddress().getHostAddress();
	}

	public void setConexao(Socket conexao) {
		this.conexao = conexao;
	}

	public BufferedReader getEntrada() {
		return entrada;
	}

	public void setEntrada(BufferedReader entrada) {
		this.entrada = entrada;
	}

	public BufferedWriter getSaida() {
		return saida;
	}

	public void setSaida(BufferedWriter saida) {
		this.saida = saida;
	}

	@Override
	public String toString() {
		return nome;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((conexao == null) ? 0 : conexao.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Usuario other = (Usuario) obj;
		if (conexao == null) {
			if (other.conexao != null)
				return false;
		} else if (!this.getIp().equals(other.conexao.getLocalAddress().getHostAddress()))
			return false;
		return true;
	}

	public void disconnect() throws IOException {
		entrada.close();
		saida.close();
		conexao.close();
	}

	
}

Preciso de uma ajuda com isso galera. Estou fazendo especialização em Java e tenho problema quando descomento a linha 47 do ChatClient a aplicação trava e não permite o envio de mensagens.

Criado 12 de novembro de 2007
Ultima resposta 22 de set. de 2011
Respostas 61
Participantes 20