Bom pessoal, nao sabendo nem sequer por onde começar
a logica que pensei seria assim: qdo o cliente desconectar , tirar ele da lista de clientes pra qual o serv envia todas mensagens
dado esse sistema abaixo, alguma dica sobre como fazer?
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
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 ArrayList<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 conexão 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 thread
TrataCliente tc = new TrataCliente(cliente.getInputStream(), this);
new Thread(tc).start();
}
}
public void distribuiMensagem(String msg) {
// envia msg para todo mundo
for (PrintStream cliente : this.clientes) {
cliente.println(msg);
System.out.println(msg);
}
}
}
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Cliente {
public static void main(String[] args) throws UnknownHostException, IOException {
// dispara cliente
String nome = args.length>0?args[0]:"sem nome";
new Cliente("127.0.0.1", 12345, nome).executa();
}
private String host;
private int porta;
private String nome;
public Cliente (String host, int porta, String nome) {
this.host = host;
this.porta = porta;
this.nome = nome;
}
public void executa() throws UnknownHostException, IOException {
Socket cliente = new Socket(this.host, this.porta);
System.out.println("O cliente se conectou ao servidor!");
// 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(nome + ": " + teclado.nextLine());
}
saida.close();
teclado.close();
cliente.close();
}
}
import java.io.InputStream;
import java.util.Scanner;
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();
}
}
import java.io.InputStream;
import java.util.Scanner;
public 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());
}
}
}
Quando o servidor fizer o envio, ele pede uma confirmação do cliente.
Se o cliente não confirmar, quer dizer que ele não está mais conectado, então o servidor o tira da lista.
[quote=davidbuzatto]Quando o servidor fizer o envio, ele pede uma confirmação do cliente.
Se o cliente não confirmar, quer dizer que ele não está mais conectado, então o servidor o tira da lista.
[]'s[/quote]
obrigado
mas como eu implemento um pedido de confirmação de que o cliente esta conectado?
a estrutura com IF eu ja imagino mas a linha de codifo q pede confirm ainda nnao
Eu estava pronto para te ajudar a fazer essa comunicação ali que nosso colega davidbuzatto comentou… Mas acho que encontrei uma forma mais simples… Fiz umas classes mais enxutas aqui para ver no que dava. Aparentemente, daria pra controlar quem está conectado ou não naquele loop do TrataCliente… Dá uma olhada e tente entender o que eu fiz rs
Servidor.java
import java.net.*;
import java.util.ArrayList;
public class Servidor {
public static ArrayList<String> clientes;
public static void main(String args[]) throws Exception {
clientes = new ArrayList<String>();
ServerSocket servidor = new ServerSocket(12345);
int i = 0;
while(i != -1) {
Socket cliente = servidor.accept();
clientes.add(new String("cliente" + i)); // Adiciona o nome do cliente na array...
mostraClientes(); // Mostra os clientes conectados pela arraylist clientes...
TrataCliente tc = new TrataCliente(cliente.getInputStream(), servidor, i); // Fica escutando a entrada...
new Thread(tc).start();
i++; // Incrementa o ID do cliente...
}
System.out.println("Servidor fechou!");
}
public static void mostraClientes() {
for(String cli : Servidor.clientes) { System.out.println(cli); }
}
}
TrataCliente.java
import java.net.*;
import java.io.InputStream;
import java.util.Scanner;
public class TrataCliente implements Runnable {
private InputStream cliente;
private ServerSocket servidor;
private int id;
public TrataCliente(InputStream cliente, ServerSocket servidor, int id) {
this.cliente = cliente;
this.servidor = servidor;
this.id = id; // Grava o ID na instância
}
public void run() {
System.out.println("Cliente " + id + " Conectado!");
Scanner s = new Scanner(this.cliente);
while (s.hasNextLine()) { // Este é o loop em que o sistema fica, enquando o cliente estiver conectado...
}
// Saiu do loop, é porque desconectou...
Servidor.clientes.remove("cliente" + id); // Remove da lista de clientes da classe Servidor lá trás...
System.out.println("Cliente " + id + " desconectado!");
Servidor.mostraClientes(); // Mostra os clientes conectados novamente...
s.close();
}
}
E a Cliente.java que tá bem simplesinha, só para ter uma classe cliente mesmo =P
import java.net.*;
public class Cliente {
public static void main(String args[]) throws Exception {
Socket cliente = new Socket("127.0.0.1", 12345);
while(cliente.isConnected()) {}
}
}
Tentei comentar as partes principais que fariam este processo… Tenho quase certeza que este não seria o jeito mais correto de se fazer isso (tenho um background em outras linguagens, mas no geral sou pitoco =P) mas tá funcionando… rs
Dá para testar isso dai, rodando o Servidor, ai abrindo uns 3 Clientes… depois vai fechando os clientes (pode ser fora de ordem) para ver ele sendo retirado da lista…
quando um socket desconecta ele envia um null no output, assim basta vc implementar uma instrucao que le as mensagens, se vier null o cliente foi desconectado.
realmente interesante friend
ajudou a me dar uma outra visao
e eu tb nao fazia ideia de q sair daqule looping era o sinal de que o cliente desconectou… bastando remover da lista
mas uma duvida…
…na tua classe TrataCliente na linha 21 nao ta faltando implementar a distribuição das mensagens?
Está faltando sim. =P Eu removi a linha pra não ter que colocar o método lá na classe Servidor… Só copiei a estrutura básica da TrataCliente mesmo para ver como funcionava…
Está faltando sim. =P Eu removi a linha pra não ter que colocar o método lá na classe Servidor… Só copiei a estrutura básica da TrataCliente mesmo para ver como funcionava…
Valeuu[/quote]
bah desculpa…só depois q rodei é que vi q era só pra testar a funcionalidade de detectar o cliente desconectado e a retirada do nome dele da lista.
realmente funfa
parabens e thank’s men
bela dica friend
nao sabia disso
mais uma forma pra mim testar.
relativo a essa questao de detectar quando um cliente do chat desconectou e retira-lo da lista me impressionei que a galera ai, incuindo tu, ja me mostraram umas 2 ou 3 maneiras dif de fazer.
quero testar o teu tb !
ja to a dias nesse siteminha de chat e ainda vou ficar mais uns até testar tudo que me falaram aqui
thank’s men :lol:
keepalive é propriedade de socket do sistema operacional. Ele fica “pingando” o cliente, deixando a conexão ativa, e quando o cliente não retorna o ping, ele fecha a conexão sozinho(verifica se o pacote teve timeout). Aí bastaria você verificar se o socket está aberto ou não. Só mexi com socket em C, não mexi em java, possivelmente não muda muito. Dá uma estudada no keep alive, acho que no java ele vai disparar uma excessão quando o cliente se desconecta.
valeu cara
nao sabia disso… desssa forma parece bem facil.
pra testar tudo que falaram pra mim vou ficar mais uns dias nesse programinha.
mas ta velendo a pena cada segundo
thank’s