Opa Galera sou iniciante em Java e estou precisando criar uma Thread que fique executando enquanto um cliente estiver conectado via socket.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start.");
System.out.println(Thread.currentThread().getName()+" End.");
}
}, delay, intervalo em milissegundos);
Você quer que cada conexão seja tratada em uma thread separada?
import java.net.Socket;
import java.net.ServerSocket;
import java.io.IOException;
class Main {
public static void main(String[] args) {
int porta = leEntrada(args);
try {
ServerSocket server = new ServerSocket(porta);
while (true) {
Socket client = server.accept();
new Thread(codigoExecutadoPelaThread(client)).start();
}
} catch (IOException ex) {
System.err.println("Ocorreu um erro na thread principal do servidor.");
ex.printStackTrace();
}
}
public static int leEntrada(String[] args) {
int porta = -1;
try {
porta = Integer.parseInt(args[0]);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException ex) {
System.err.println("Chamda inválida. Uso: java Main <porta>");
System.exit(1);
}
return porta;
}
public static Runnable codigoExecutadoPelaThread(Socket client) {
return () -> {
// aqui você coloca o código que vai ser executado numa nova thread,
// que utiliza o client.
// Eu acho melhor você criar uma classe que implementa a interface Runnable,
// mas isso aqui vai servir.
try {
client.close();
} catch (IOException ex) {
System.err.println("Erro ao tentar fechar o socket.");
ex.printStackTrace();
}
};
}
}
Assim. Quero fazer uma Thread com socketServer que fique esperando conexões de cliente. Cada cliente terá um socketServer e uma porta. Quando um cliente desconectar ele enviara para essa Thread uma String “Fim” antes de desconectar. Ao se desconectar a Thread deverá novamente aguardar conexões deste mesmo cliente. Pra ser mais exato serão 4 clientes.
Desculpem a gambiarra mas estou aprendendo:
private void iniciarServidor()
{
try {
serverSocket5 = new ServerSocket (2345);
serverSocket6 = new ServerSocket (2346);
serverSocket7 = new ServerSocket (2347);
serverSocket8 = new ServerSocket (2348);
jLabelServidor.setText(“Servidor Online”);
} catch (IOException ex) {
Logger.getLogger(Menu_Jf.class.getName()).log(Level.SEVERE, null, ex);
}
new Thread()
{
public void run()
{
try
{
while(true)
{
Socket socket5 = serverSocket5.accept();
if (socket5.isBound()== true)
{
JOptionPane.showMessageDialog(null,"Leitor 5. Conexão Iniciada com IP: \n"+socket5.getInetAddress().toString()+"Porta: "+socket5.getPort());
Recebido = new DataInputStream(socket5.getInputStream());
if(Recebido.readUTF().equals("FIM"))
{
//JOptionPane.showMessageDialog(null,"Leitor 5 desconectou");
Recebido = null;
}
}
/////Aqui gostaria que a Thread voltasse a esperar conexão do mesmo cliente que desconectou como um loop que fica atualizando se o cliente esta conectado.
}.start(); ///
Como sou iniciante em java e ainda mais em Thread não entendi exatamente como funciona uma Thread para ela ficar executando em segundo plano junto ao main. Desde já agradeço a ajuda
Vou assumir que você entendeu como funcionam threads no sistema operacional. Quando você cria um objeto do tipo Thread, esse objeto representa uma thread física do sistema. Ao chamar o método start, você inicializa a execução em paralelo dessa thread criada.
Thread t = new Thread(runnable);
// essa chamada ao método start() retorna imediatamente,
// e a thread que estamos agora continua
// executando normalmente.
t.start();
outraOperacao();
outraOperacao();
//...
Quando chamamos o start(), a nova thread começa sua execução, de forma independente à thread que a criou, um fluxo de execução completamente diferente. É como se fossem dois programas rodando agora.
O seu raciocínio é o seguinte, pelo que eu entendi: você quer uma thread dedicada para cada cliente, correto? Eu faria de uma maneira um pouquinho diferente, como mandei no exemplo para você ali antes.
- A thread principal abre o servidor e espera conexões infinitamente
- Quando chega uma nova conexão (ou seja, quando o método
accept()retorna), uma nova thread é criada para se comunicar com o cliente - No código da thread, eu faria com que o cliente se identificasse (com um número ou uma string, por exemplo), e a partir daí saberia o que fazer.
Porém, vou tentar te dar algumas ideias do que fazer para continuar com a tua linha de raciocínio.
Você pode fazer o seguinte:
- Continuar o que fez, associando de forma fixa uma porta para cada cliente;
- Cria uma classe que herda de
Thread, e implementa o métodorun. Para o objeto dessa nova classe, você vai passar qualquer tipo de informação de contexto necessária para que ele identifique o cliente. - O método
runvai ficar escutando na porta determinada para o cliente, e quando chegar uma conexão, vai saber o que fazer (baseado nos parâmetros passados)
Vou tentar exemplificar isso da forma mais sucinta possível, para que tu entenda e generalize para o teu caso específico, ok?
Vamos lá:
import java.net.Socket;
import java.net.ServerSocket;
import java.io.IOException;
class Main {
public static void main(String[] args) {
ThreadCustomizada t1 = new ThreadCustomizada(2345, "Cliente 1");
ThreadCustomizada t2 = new ThreadCustomizada(2346, "Cliente 2");
ThreadCustomizada t3 = new ThreadCustomizada(2347, "Cliente 3");
ThreadCustomizada t4 = new ThreadCustomizada(2348, "Cliente 4");
// até aqui tem apenas 1 thread rodando (na verdade tem outras, o Garbage Collector por exemplo, mas enfim)
t1.start(); // a partir daqui existem 2 threads rodando
t2.start(); // 3 agora
t3.start(); // 4
t4.start(); // 5 threads rodando
// aqui a thread principal morre quando acaba o método main,
// mas as outras 4 estão executando, por isso o programa continua até que todas morram
}
}
class ThreadCustomizada extends Thread {
private final int porta;
private final String nomeDoCliente;
/*
pode passar o que quiser pro construtor,
tudo o que for necessário para lidar com o cliente
*/
ThreadCustomizada(int porta, String nomeDoCliente) {
this.porta = porta;
this.nomeDoCliente = nomeDoCliente;
}
@Override
public void run() {
try {
ServerSocket server = new ServerSocket(this.porta);
// Fica esperando o cliente se conectar sempre
while (true) {
// essa chamada bloqueia (fica travada, não sai do lugar)
// até que o cliente se conecte. Quando isso acontecer,
// o método accept retorna e a execução continua.
Socket client = server.accept();
// aqui você faz tudo o que quiser com o socket
// no momento que o cliente sair, o while reinicia
// e fica esperando por aquele cliente específico novamente,
// na mesma porta
client.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Obrigadão pela ajuda, era isso mesmo que eu queria fazer. Só agora estou com um problema quanto as portas de cada socket. Pois quando o cliente 2 se conecta e o 1 está desconectado ele não respeita o número da porta setado e utiliza o socket do Cliente 1. Desde já muito obrigado pela ajuda.