Fórum Socket para conexão entre Servidor e vários Clientes. #569266
09/04/2009
Estou tentando criar um chat onde os clientes enviam mensagens para o servidor e este mandam as mensagens para todos os clientes.
Problema: quando tenho um único cliente o servidor envia a mensagem corretamente, mas quendo tenho dois clientes e o 1ª envia uma mensagem está vai apenas para o 2ª e não para o 1ª. outro detalhe é que apenas uma mensagem é enviada para o 2ª, quando tento enviar outra ele não vai nem para o 1ª e nem para 2ª.
Gostaria que alguém pudesse mim esclarecer isto, pois estou iniciando no java é tenho muitas dúvidas.
Detalhes: estou usando ObjectOutputStream e ObjectInputStream
Posts
09/04/2009
Marcos Pereira
Bom, se o 1º é quem está enviando, faz um pouco de sentido que ele não receba de volta a propria mensagem. No mais, há poucos detalhes para saber qual o seu problema. Está usando sockets tcp ou udp?! Como está o esquema de threads do seu servidor?!
valeuz...
pra mim faz sentido quem manda receber a sua mensagem...
mas isso nao importa..
Problema: quando tenho um único cliente o servidor envia a mensagem corretamente, mas quendo tenho dois clientes e o 1ª envia uma mensagem está vai apenas para o 2ª e não para o 1ª. outro detalhe é que apenas uma mensagem é enviada para o 2ª, quando tento enviar outra ele não vai nem para o 1ª e nem para 2ª.
fica dificil responder sem ver o codigo..
tb acho que tem que receber... td cliente de chat (IRC, ICQ, MSN, etc) vc ve o que vc falou....
q caos fica falano meia hora com uma pessoa e nao ve suas proprias falas.... eu ficaria meio perdido....
;)
td mundo que manda tb recebe.... seria algo assim.... vc manda a mensagem pro servidor, q manda para TODO mundo.... no caso de ser uma msg privada, o servidor envia para quem mandou e quem recebe..
Realmente... sem o cod. fica dificil... =(
Ae amigo, eu fiz um chat interno da empresa onde trabalho e depois de vários testes com ObjectInputStream e ObjectOutputStream percebi que eles não funcionavam como eu esperava, então passei a usar DataInputStream para ler e PrintWriter para escrever no socket.
O Eskema que utilizei no chat é o seguinte, criei uma classe usuário, que armazenava dentro dela o socket do usuario, nick etc... cada vez que um cliente se conectava eu coletava essas informacoes e armazenava numa LinkedList um Object Usuario, dessa forma quando uma nova mensagem chegava tudo que tinha que fazer era varrer a LinkedList com Iterator e enviar a mensagem para os demais clientes.
Se quiser posso lhe enviar o chat, mas faz tempo que não dou manutenção dele, ele tem interface gráfica e é acompanhado de um Servidor que pode chutar ou não os usuarios.
diego@exactus.com.br
Galera, aí vai o código do meu servidor. Lembrando que, com um usuário ele responde a todas mensagens enviadas. O problema é quando tem mais de um usuário ele não envia a mensagem para todos.
Obrigado pela ajuda.
public class Teste {
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
public Teste() {
try {
server = new ServerSocket( 5000 );
while ( true ) {
System.out.println( "Aguardando conexão ..." );
connection = server.accept();
System.out.println( connection.getInetAddress().getHostName() );
ThreadServer ts = new ThreadServer();
ts.start();
}
}
catch ( EOFException eofException ) {
System.out.println( "Cliente fechou conexão." );
}
catch ( IOException ioException ) {
ioException.printStackTrace();
}
}
public class ThreadServer extends Thread {
public void run() {
try {
output = new ObjectOutputStream( connection.getOutputStream() );
input = new ObjectInputStream(connection.getInputStream() );
ProcessaConexao();
closeConnection();
}
catch (IOException ex) {
}
}
}
private void ProcessaConexao() throws IOException
{
String message = "Conectado";
output.writeObject( message );
while (true) {
try {
message = ( String ) input.readObject();
output.writeObject( message );
}
catch ( ClassNotFoundException classNotFoundException ) {
}
}
}
private void closeConnection() throws IOException {
output.close();
input.close();
connection.close();
}
public static void main( String args[] )
{
Teste app = new Teste();
}
}
alysson
vc tem de alguma forma guardar a referencia para todos os clientes que estao no chat em um certo momento..
assim que alguem manda um objeto mensagem, vc tem q repassar para todos os clientes conectados atraves do output de cada cliente
vc mantem apenas 1 referencia de input e output.. no caso vc tem q ter 1 input e 1 output para cada cliente conectado...
como o avenger falou, vc pode ter uma classe Client que guarda o socket, o input e output de 1 determinado cliente.. o seu thread deve conhecer apenas 1 cliente.. quando ele receber uma informacao, ele varre uma lista de clientes e escreve nos outputs deles..
nao sei se fico mto confuso.. qq coisa pergunta...
Galera já consegui. Desde já quero agradecer a todos pela ajuda. :o
[quote="alysson"]Galera já consegui. Desde já quero agradecer a todos pela ajuda. :o
Que tal colocar a solucao para todo mundo aqui?
:!: :!:
Boa noite amigos,to fazendo um chat aqui e to com dificuldade pra mandar a mensagem somente pra um cliente.
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) {
((PrintStream) this.clientes).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();
}
}
}
[quote="loverboy"]Boa noite amigos,to fazendo um chat aqui e to com dificuldade pra mandar a mensagem somente pra um cliente.
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) {
((PrintStream) this.clientes).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();
}
}
}
muito interessante, o fato de voce ter dificuldade... mas será que podemos ajudar?
pelo código imagino que não está conseguindo mandar mensagem alguma.
((PrintStream) this.clientes).println(msg);
não funciona desse jeito. clientes é uma List, não tem o método println e nem tem como fazer um cast para um PrintStream. Tem que percorrer a lista, se for para mandar uma mensagem para todos os clientes:
for (PrintStream out : this.clientes) {
out.println(msg);
}
sugestão para mandar a mensagem para um único cliente é fazer o tratamento do cliente, inclusive mandar a mensagem, na classe TrataCliente. Para isso terá que tambem passar o PrintStream para o construtor (ou passar apenas o Socket e deixar o TrataCliente tratar do "socket"). Dentro do TrataCliente voce manda a mensagem para o cliente .
[]