[Resolvido] Ao finalizar Thread, conexão do Socket é fechada!?

Salve Gujeiros.

Estou realizando um trabalho da faculdade usando socket que visa o monitoramento do tráfego de dados nos computadores da rede.

Estou com o seguinte problema:

Quando um cliente se conecta ao servidor, é iniciada uma thread no servidor para tratar a conexão com esse cliente e tb é iniciada uma thread no cliente que envia os dados ao servidor a cada intervalo de tempo.

O problema é que ao finalizar a thread no cliente, ele fecha o socket de conexão com o servidor.

Vou colocar aqui os trechos mais importantes do código para tentar mostrar como estou fazendo.

Funcoes.java:
Classe que cria as threads no cliente.

No método monitoraMáquina crio uma nova thread passando como parâmetro o socket de conexão com o servidor.
No método novaThreadCliente coloco essa thread numa List de Threads.
No método executaComando estou recebendo do servidor o comando “kill” pra matar TODAS as threads que estão na minha lista, porém NÃO DESEJO fechar o socket de conexão.

public class Funcoes implements ThreadListener{

	private Socket socket;
        private List<ClienteThread> threadsEmExecucao = new ArrayList<ClienteThread>();
	
	public String executaComando(Socket socket, String comando){
				
                if (com[0].equals("kill")){
                    for (ClienteThread clienteExecucao : threadsEmExecucao){
                            clienteExecucao.pararThread();
                    }

		}
                
	}

	private void monitoraMaquina(Socket socket, List<String> dados, String tempo, String quantidade) {
            Runnable runnable = new ClienteThread(socket, dados, tempo, quantidade, this);
            Thread threadCliente = new Thread(runnable);
            threadCliente.start();
	}

    public void novaThreadCliente(ClienteThread thread) {
        threadsEmExecucao.add(thread);
    }
}

ClienteThread.java:
Thread que fica enviando dados ao servidor.

Como pode ser visto, na classe Funcoes faço a chamada do método pararThread() que seta a flag que controla o while{} para false forçando o término da Thread.

public class ClienteThread implements Runnable {

	public ClienteThread(Socket socket, List<String> dados, String tempo, String quantidade, ThreadListener listener) {
		this.socket = socket;
		this.dados = dados;
		this.tempo = tempo;
		this.quantidade = quantidade;
                this.listener = listener;
		runThread = true;
	}
	
	public void run(){
		try {
			out = new PrintWriter(socket.getOutputStream(), true);

                        listener.novaThreadCliente(this);
			while (runThread) {
				// envia string ao servidor

				Thread.sleep(Integer.parseInt(tempo));

			}		
		} catch (Exception e){
			
		}
	}
	
	public void pararThread(){
		runThread = false;
	}

}

Porém, quando minha Thread é finalizada, o socket tem sua conexão fechada.

Alguém sabe como posso terminar essa thread sem fechar minha conexão com o socket?

Espero que tenha sido claro. Qualquer dúvida é só perguntar. :slight_smile:

Se alguém puder ajudar, agradeço.

[]'s

...
private Socket socket;
...
	private void monitoraMaquina(Socket socket, List<String> dados, String tempo, String quantidade) {
            Runnable runnable = new ClienteThread(socket, dados, tempo, quantidade, this);
            Thread threadCliente = new Thread(runnable);
            threadCliente.start();
	}
...

E quem chama monitoraMaquina(Socket socket,…) ?

Mais especifico, quem cria o Socket?

[quote=dreamspeaker] ... private Socket socket; ... private void monitoraMaquina(Socket socket, List<String> dados, String tempo, String quantidade) { Runnable runnable = new ClienteThread(socket, dados, tempo, quantidade, this); Thread threadCliente = new Thread(runnable); threadCliente.start(); } ...

E quem chama monitoraMaquina(Socket socket,…) ?

Mais especifico, quem cria o Socket?[/quote]

Esta classe que passa o comando “monitorar” e o socket que ela criou como parâmetro para a classe Funcoes, que irá executar o monitoraMáquina().

public class Controlador {
	
	// Socket para comunicação com o servidor
	private Socket socket;
	PrintWriter out;
        BufferedReader in;
        Funcoes funcoes;
    
    
	public Controlador(String ipServidor, String portaServidor){
		funcoes = new Funcoes();
		
		try {
			socket = new Socket(ipServidor, Integer.parseInt(portaServidor));
            		out = new PrintWriter(socket.getOutputStream(), true);
            		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        	} catch (UnknownHostException e) {
            		System.err.println("Servidor desconhecido.");
            		System.exit(1);
        	} catch (IOException e) {
        	    	System.err.println("N&#65533;o foi poss&#65533;vel estabelecer conex&#65533;o com o servidor.");
            		System.exit(1);
       		 }
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Controlador controlador = new Controlador("192.168.1.2", "9700");
		controlador.escutaServidor();
	}

	private void escutaServidor() {
		String comando;
		
		try {
                    
			while ((comando = in.readLine()) != null) {
			    String resultado = funcoes.executaComando(socket, comando);
			    
			    if (resultado != null) {
			        System.out.println("Resultado: " + resultado);
			        out.println(resultado);
			    }
			}


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

Ligando modo achOmetro…

Quando vc finaliza a Thread, o BufferedReader.readLine() retorna null, mesmo o Socket estando aberto ainda, porque segundo a API do dito cujo, ele retorna a linha ou “null if the end of the stream has been reached

Encontrando null, ele encerra a execucao do metodo excutaServidor() no objeto Controlador.

Faz sentido?

Abraco

[quote=dreamspeaker]Ligando modo achOmetro…

Quando vc finaliza a Thread, o BufferedReader.readLine() retorna null, mesmo o Socket estando aberto ainda, porque segundo a API do dito cujo, ele retorna a linha ou “null if the end of the stream has been reached

Encontrando null, ele encerra a execucao do metodo excutaServidor() no objeto Controlador.

Faz sentido?

Abraco[/quote]

Obrigado pela ajuda dreamspeaker

Esqueci de citar o detalhe de que em alguns testes que realizei, ao parar a thread ele finalizava também a execução da aplicação cliente, exatamente como você disse.

Não tenho como depurar o código agora parar verificar se realmente o método BufferedReader.readLine() está retornando null mas o farei assim que possível.

Agora me ficou uma dúvida de por que isto ocorre, pois o método BufferedReader.readLine() dentro do método escutaServidor() está lendo o que é escrito no socket pelo servidor. A finalização da Thread não é independente da leitura realizada no método escutaServidor()?

[]'s

Eh, numas. A Thread eh independente, mas estao ligados por um cordao umbilical que eh o Socket.

A Thread parou de escrever NO socket, o escutaServidor nao teve mais o que escutar DO socket.

Isso tudo eh um chute, porque nao testei nada aqui. Mas acho que eh por ai o caminho.

Boa sorte!

Encontrei o problema.

O leitor e escritor do socket estava sendo fechado no servidor. Logo, o método BufferedReader.readLine() não tinha mais como ler do socket e recebia null, causando o término da aplicação cliente.

Obrigado pela ajuda dreamspeaker!

[]'s