[Resolvido] Enviar mensagem para clientes (chat)

Em uma aplicação chat (cliente-servidor), preciso que: O que for digitado na tela do servidor seja repassado a todos os clientes.
Para isso criei uma lista (de sockets), onde todos os clientes que se conectarem serão adicionados.
No botão ‘enviar’ do servidor, coloquei o seguinte código:

[code]for (Socket cliente : this.clientes) {
try{
String msg = cliente.getOutputStream().toString();
System.out.println(msg); //esse print é só pra saber se ta pegando a mensagem

                try {
                    Cliente c = new Cliente("127.0.0.1", 12345); //aqui eu instancio a classe cliente para ter acesso 
                    c.txtaHistoricoC.append(msg); //a este txt
                } 
                catch (IOException ex) {
                       Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                }

        } 
        catch (IOException ex) {
            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
        }

}[/code]

Mas não funciona! Não sei se é o for que está errado, ou a forma de pegar o que foi digitado…
Outro problema, ao fazer a instanciação da classe Cliente, o servidor entende como uma “nova conexão de cliente”… :confused:

Tentei agora desta forma:
Criei uma lista de PrintStream desta vez…

for (PrintStream cliente : this.clientes) { cliente.println(mensagem); // guardei o texto digitado no txt nesta variável "mensagem" }
Mas nem mostra a mensagem…

Servidor de Socket:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package server;


import java.io.*;
import java.net.*;
import java.util.*;

/**
 *
 * @author wolmir
 */
public class ServerChat extends Thread  {

   public static void main(String args[]) {
		
//		instancia o vetor de clientes conectados
		clientes = new Vector();
		try {
//			criando um socket que fica escutando a porta 9090.
			ServerSocket s = new ServerSocket(8090);
			
//			Loop principal.
			while (true) {
//				aguarda algum cliente se conectar. A execução do
//				servidor fica bloqueada na chamada do método accept da
//				classe ServerSocket. Quando algum cliente se conectar
//				ao servidor, o método desbloqueia e retorna com um
//				objeto da classe Socket, que é porta da comunicação.
				System.out.print("Esperando alguem se conectar...");
				Socket conexao = s.accept();
				System.out.println(" Conectou!");
//				cria uma nova thread para tratar essa conexão
				Thread t = new ServerChat(conexao);
				t.start();
//				voltando ao loop, esperando mais alguém se conectar.
			}
		}
		catch (IOException e) {
//			caso ocorra alguma excessão de E/S, mostre qual foi.
			System.out.println("IOException: " + e);
		}

	}
//	Parte que controla as conexões por meio de threads.
//	Note que a instanciação está no main.
	private static Vector clientes;
//	socket deste cliente
	private Socket conexao;
//	nome deste cliente
	private String meuNome;
//	construtor que recebe o socket deste cliente
	public ServerChat(Socket s) {
            conexao = s;
	}
//	execução da thread
	public void run() {
		try {
//			objetos que permitem controlar fluxo de comunicação
			BufferedReader entrada = new BufferedReader(new
					InputStreamReader(conexao.getInputStream()));
			PrintStream saida = new
			PrintStream(conexao.getOutputStream());
			
//			primeiramente, espera-se pelo nome do cliente
			meuNome = entrada.readLine();
			
//			agora, verifica se string recebida é valida, pois
//			sem a conexão foi interrompida, a string é null.
//			Se isso ocorrer, deve-se terminar a execução.
			if (meuNome == null) {return;}
			
//			Uma vez que se tem um cliente conectado e conhecido,
//			coloca-se fluxo de saída para esse cliente no vetor de
//			clientes conectados.
			clientes.add(saida);
			
//			clientes é objeto compartilhado por várias threads!
//			De acordo com o manual da API, os métodos são
//			sincronizados. Portanto, não há problemas de acessos
//			simultâneos.
//			Loop principal: esperando por alguma string do cliente.
//			Quando recebe, envia a todos os conectados até que o
//			cliente envie linha em branco.
//			Verificar se linha é null (conexão interrompida)
//			Se não for nula, pode-se compará-la com métodos string
			String linha = entrada.readLine();
			
			while (linha != null && !(linha.trim().equals(""))) {
//				reenvia a linha para todos os clientes conectados
				sendToAll(saida, " disse: ", linha);

//				espera por uma nova linha.
				linha = entrada.readLine();
			}
//			Uma vez que o cliente enviou linha em branco, retira-se
//			fluxo de saída do vetor de clientes e fecha-se conexão.
			sendToAll(saida, " saiu ", "do chat!");
			clientes.remove(saida);
			conexao.close();
		}
		catch (IOException e) {
//			Caso ocorra alguma excessão de E/S, mostre qual foi.
			System.out.println("IOException: " + e);
		}
	}
//	enviar uma mensagem para todos, menos para o próprio
	public void sendToAll(PrintStream saida, String acao,
			String linha) throws IOException {
		Enumeration e = clientes.elements();
		while (e.hasMoreElements()) {
//			obtém o fluxo de saída de um dos clientes
			PrintStream chat = (PrintStream) e.nextElement();
//			envia para todos, menos para o próprio usuário
			if (chat != saida) {chat.println(meuNome + acao + linha);}
		}
	}
}

Cliente de socket:

package clientechat;

import java.io.*;
import java.net.*;
public class ClientedeChat extends Thread {
//	Flag que indica quando se deve terminar a execução.
	private static boolean done = false;
	public static void main(String args[]) {
		try {
//			Para se conectar a algum servidor, basta se criar um
//			objeto da classe Socket. O primeiro parâmetro é o IP ou
//			o endereço da máquina a qual se quer conectar e o
//			segundo parâmetro é a porta da aplicação. Neste caso,
//			utiliza-se o IP da máquina local (127.0.0.1) e a porta
//			da aplicação ServidorDeChat. Nada impede a mudança
//			desses valores, tentando estabelecer uma conexão com
//			outras portas em outras máquinas.
			Socket conexao = new Socket("192.168.2.193", 8090);
                        
//		Basuma vez estabelecida a comunicação, deve-se obter os
//			objetos que permitem controlar o fluxo de comunicação
			PrintStream saida = new PrintStream(conexao.getOutputStream());
			
//			enviar antes de tudo o nome do usuário
			BufferedReader teclado = new BufferedReader(new InputStreamReader(System.in));
			System.out.print("Entre com o seu nome: ");
			String meuNome = teclado.readLine();
			saida.println(meuNome);
                        
//			Uma vez que tudo está pronto, antes de iniciar o loop
//			principal, executar a thread de recepção de mensagens.
			Thread t = new ClientedeChat(conexao);
			t.start();
                        
//			loop principal: obtendo uma linha digitada no teclado e
//			enviando-a para o servidor.
			String linha;
			while (true) {
//				ler a linha digitada no teclado
				System.out.print("> ");
				linha = teclado.readLine();
//				antes de enviar, verifica se a conexão não foi fechada
				if (done) {break;}
//				envia para o servidor
				saida.println(linha);
			}
		}
		catch (IOException e) {
//			Caso ocorra alguma excessão de E/S, mostre qual foi.
			System.out.println("IOException: " + e);
		}
	}
//	parte que controla a recepção de mensagens deste cliente
	private Socket conexao;
//	construtor que recebe o socket deste cliente

	public ClientedeChat(Socket s) {
		conexao = s;
	}
//	execução da thread
	public void run() {
		try {
			BufferedReader entrada = new BufferedReader
			(new InputStreamReader(conexao.getInputStream()));
			String linha;
			while (true) {
//				pega o que o servidor enviou
				linha = entrada.readLine();
//				verifica se é uma linha válida. Pode ser que a conexão
//				foi interrompida. Neste caso, a linha é null. Se isso
//				ocorrer, termina-se a execução saindo com break
				if (linha == null) {
					System.out.println("Conexão encerrada!");
					break;
				}
//				caso a linha não seja nula, deve-se imprimi-la
				System.out.println();
				System.out.println(linha);
				System.out.print("...> ");
			}
			

		}
		catch (IOException e) {
//			caso ocorra alguma exceção de E/S, mostre qual foi.
			System.out.println("IOException: " + e);
		}
//		sinaliza para o main que a conexão encerrou.
		done = true;
	}
}

Crie um projeto no netBeans e crie as duas classes depois rode o servidor e rode alguns clientes é um exemplo bem util…

Wolmir Garbin

Wolmir, consegui resolver meu problema estudando o exemplo anteriormente.
O método que envia mensagem pelo servidor ficou desta maneira:

private void enviaTodos(String texto, Socket remetente) { for (Socket cliente : this.clientes) //clientes é a lista { if (cliente != remetente) //para não mandar a mensagem repetida para ele mesmo { try { PrintWriter out = new PrintWriter(cliente.getOutputStream(), true); out.println(texto); } catch (IOException ex) { Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex); } } } }
Já no método que recebe, no cliente, ficou assim:

[code]public void conexao() throws IOException, UnknownHostException
{
try
{
this.servidor = new Socket(“127.0.0.1”, 12345);

        txtaHistoricoC.append("Nova conexão com o servidor\n");

        BufferedReader entrada = new BufferedReader(new InputStreamReader(this.servidor.getInputStream()));
        String linha;

        while (true)
        {
            linha = entrada.readLine();
            if (linha == null)
            {
                break;
            }
            System.out.println(linha);

            if (!(linha == null)) txtaHistoricoC.append("\n" + linha.toString());
        }
    } catch(IOException e){
        txtaHistoricoC.append("Servidor não está disponível!");
    } catch (Exception e){}
}[/code]

Fico feliz por ter ajudado…
Vc tem msn?
Quem sabe quando precisar de alguma coisa posso te ajudar mais…
Se tiver manda no meu email wolmirgarbin@gmail.com

Wolmir, obrigada! Já enviei o email! 8)