Thread + Socket (Client/Servidor) (RESOLVIDO)

13 respostas
F

boa tarde pessoal
estou com uma outra duvida aqui em relacao ao thread usando socket
eu fiz um prog que qndo cliente manda msg o servidor responde com quantos characters o cliente enviou
funcionou normal
mais agora preciso colocar varios clientes utilizando o thread e do jeito que eu estou fazendo nao esta funcionando de jeito nenhum
se alguem puder por favor me da 1 luz =)

Cliente:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;


public class Cliente extends Thread  {
	String sentence;
    String modifiedSentence;
    Socket Client = null;
	  public static void main (String[] args)
	  {
    Cliente teste1 = new Cliente();
		  
	      Thread Conserv = new Thread(teste1);	
	      
	      Thread Conserv2 = new Thread(teste1);
	      
	      Thread Conserv3 = new Thread(teste1); 
	    	      
	      Conserv.start();
	    	   
	      Conserv2.start();
    	   
	      Conserv3.start();
	      
	  }
	  public void run()
	  {
	    	 MandarConectar();
	        	 
	  }
	  public void MandarConectar(){
		 
		  try{
			  if(Client == null){
				// Cria um Socket cliente passando como parâmetro o ip e a porta do servidor   
		           Client = new Socket("localhost", 40000);}
			 
	           // Cria um buffer que armazenará as informações de entrada do teclado
	           BufferedReader inFromUSer = new BufferedReader(new InputStreamReader(System.in));
	           
	           // Cria um stream de saída 
	           DataOutputStream outToServer = new DataOutputStream(Client.getOutputStream());
	  
	           // Cria um buffer que armazenará as informações retornadas pelo servidor
	           BufferedReader inFromServer = new BufferedReader(new InputStreamReader(Client.getInputStream()));
	   
	           // Atribui as informações armazenadas no buffer do teclado à variável "sentence"
	           sentence = inFromUSer.readLine();
	   
	           // Disponibiliza as informações contidas em "sentence" para a stream de saída do cliente
	           outToServer.writeBytes(sentence + "\n");
	   
	           // Atribui as informações modificadas pelo servidor na variável "modifiedSentence"
	           modifiedSentence = inFromServer.readLine();
	   
	           // Imprime no console do cliente a informação retornada pelo servidor
	           System.out.println("do servidor: " + modifiedSentence);
	   
	           // Fecha o Socket
	         Client.close();   
	      } catch (UnknownHostException e) {
	          // TODO Auto-generated catch block
	          e.printStackTrace();
	      } catch (IOException e) {
	          // TODO Auto-generated catch block
	          e.printStackTrace();
	      }
	  }
}
Servidor:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Servidor {

   public static void main(String[] args) {

       String clientSentence;
       String capitalized;
       ServerSocket socket = null;
       Socket connectionSocket = null;
       try {
 
           // Cria um SocketServer (Socket característico de um servidor)
           socket = new ServerSocket(40000);
           while(true) {    
    
               /* Cria um objeto Socket, mas passando informações características de um servidor,
                *no qual somente abre uma porta e aguarda a conexão de um cliente 
                */
               connectionSocket = socket.accept();
               
               // Cria uma buffer que irá armazenar as informações enviadas pelo cliente
               BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
    
               // Cria uma stream de sáida para retorno das informações ao cliente
               DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
    
               // Faz a leitura das informações enviadas pelo cliente as amazenam na variável "clientSentence"
               clientSentence = inFromClient.readLine();
    
               /* Faz uma modificação na String enviada pelo cliente, simulando um processamento em "back-end"
                * antes de retorná-la ao cliente
                */
               capitalized = clientSentence.toLowerCase();
    
               // Imprime a a String modificada no console do servidor
               System.out.println("Voce digitou: "+capitalized.length()+" letras");
    
               // Retorna as informações modificadas, ao cliente
               outToClient.write(capitalized.length()); 
           } 
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }finally{
           try {
        	   connectionSocket.close();
			socket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
       }
    }
}

Obriigado atE+

13 Respostas

ViniGodoy
Você precisa criar um cliente para cada Thread:
public static void main (String[] args) {
    Thread Conserv = new Thread(new Cliente());	
    Thread Conserv2 = new Thread(new Cliente());
    Thread Conserv3 = new Thread(new Cliente()); 
	    	      
    Conserv.start();
    Conserv2.start();
    Conserv3.start();
}

No lado do servidor, também será necessário criar uma classe que trabalhe com um Socket. E criar uma thread para cada "accept()" que o servidor receber.

F

esse thread para cada accept

seria o thread que enviaria a mensagem ao cliente?

tipo socket.acept for verdadeiro
ai mando a msg?
e isso?

ViniGodoy

Para cada cliente conectado, o accept() do ServerSocket cria um Socket, que representa aquele cliente. Então, você deve disparar uma thread para lidar com o cliente recebido.

O while do servidor vai ficar mais ou menos assim:

while (true) {
   ClienteHandler handler = new ClientHandler(socket.accept());
   Thread t = new Thread(handler);
   t.start();
}

A classe ClientHandler é quem vai efetivamente conversar com o cliente.

Portanto, todo esse código deve ser movido para o método run ClientHandler:

// Cria um buffer que armazenará as informações de entrada do teclado  
                BufferedReader inFromUSer = new BufferedReader(new InputStreamReader(System.in));  
                  
                // Cria um stream de saída   
                DataOutputStream outToServer = new DataOutputStream(Client.getOutputStream());  
         
                // Cria um buffer que armazenará as informações retornadas pelo servidor  
                BufferedReader inFromServer = new BufferedReader(new InputStreamReader(Client.getInputStream()));  
          
                // Atribui as informações armazenadas no buffer do teclado à variável "sentence"  
                sentence = inFromUSer.readLine();  
          
                // Disponibiliza as informações contidas em "sentence" para a stream de saída do cliente  
                outToServer.writeBytes(sentence + "\n");  
          
                // Atribui as informações modificadas pelo servidor na variável "modifiedSentence"  
                modifiedSentence = inFromServer.readLine();  
          
                // Imprime no console do cliente a informação retornada pelo servidor  
                System.out.println("do servidor: " + modifiedSentence);  
          
                // Fecha o Socket  
              Client.close();

Seu código atual até funciona, pois sua comunicação com o cliente é curta, e ele deve retornar muito rapidamente ao accept. Mas sem a thread, ele não funcionará, pois o cliente manteria o servidor ocupado, e o código poderia demorar demais a voltar para o accept.

Com a thread vc permite várias comunicações simultâneas do lado do servidor.

ViniMunhoz

Cada requisição feita para o servidor deve ser tratada em uma thread separada para não ocupar a porta que estiver atendendo as requisições, senão vc vai ter problemas.
Cada Socket recebido pelo accept vai para uma das threads.

ViniMunhoz

Quando cliquei para responder não vi a resposta do ViniGodoy… mas ele está explicando melhor que eu… rs

F

hmm clareou bastante aqui
obrigado
ViniGodoy e ViniMunhoz

F

tipo o socket eu continuo criando na classe do servidor?
ai eu mando o socket aceito para a classe handle?
e a classe handle q vai retornar a mensagem pro cliente
e isso?

ViniGodoy

Isso.

F
Galera fiz do seguinte modo da uma olhada para ver oq acham Servidor:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;


public class Servidor extends Thread{
	
	public static void main(String args[]){
		ServerSocket s = null;
		try{//tentando criar uma conexao
			s = new ServerSocket(40000);//Cria um SocketServer com porta 40000
			while(true){
	           /* Cria um objeto Socket, mas passando informações características de um servidor,
	            *no qual somente abre uma porta e aguarda a conexão de um cliente 
	            */
				Socket conexao = s.accept();
				
				//cria uma thread que envia a conexao
				Thread t = new Servidor(conexao);
				
				//inicia a thread t
				t.start();
			}
		}catch(IOException e){
			System.out.println("IOException "+e);
		}
	}
	private Socket conexao;
	public Servidor(Socket s){//recebe o valor do socket enviado na thread
		conexao = s;
	}
	public void run(){
		try{
			
			// Cria uma buffer que irá armazenar as informações enviadas pelo cliente
			BufferedReader inFromClient = new BufferedReader(new InputStreamReader(conexao.getInputStream()));
		    
            // Cria uma stream de sáida para retorno das informações ao cliente
            DataOutputStream outToClient = new DataOutputStream(conexao.getOutputStream());
 
            // Faz a leitura das informações enviadas pelo cliente as amazenam na variável "EscritaCliente"
            String EscritaCliente = inFromClient.readLine();
 
            // Imprime a String modificada no console do servidor
            System.out.println("Voce Digitou: "+EscritaCliente.length()+" Digitos");
            
            // Imprime a String modificada no console do cliente
            outToClient.writeBytes("Voce Digitou: "+EscritaCliente.length()+" Digitos");
		}catch(IOException e){
			System.out.println("IOException "+e);
		}
	}
	
}
Cliente
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;


public class Cliente extends Thread {
	public static void main(String args[]){
		try{
			// Cria um Socket conexao passando como parâmetro o ip e a porta do servidor 
			Socket conexao = new Socket("localhost",40000);
			
			//cria uma thread que envia a conexao
			Thread t = new Cliente(conexao);
			
			//inicia o thread
			t.start();
			
		}catch(IOException e){
			System.out.println("IOException"+e);
		}
	}
	private Socket conexao;
	public Cliente(Socket s){//recebe o valor do socket enviado na thread
		conexao = s;
	}
	public void run(){
		try{//cria uma printstream para pegar as informacoes enviadas do servidor
			PrintStream saida = new PrintStream(conexao.getOutputStream());
			
			//cria um bufferedreader para receber informacoes digitadas
			BufferedReader teclado = new BufferedReader (new InputStreamReader(System.in));
			
			//escreve uma mensagem ao usuario
			System.out.println("entre com algum digito");
			
			//digito recebe o valor digitado pelo usuario
			String digito = teclado.readLine();
			
			//imprime o valor de digito
			saida.println(digito);
			
			
			BufferedReader entrada = new BufferedReader(new InputStreamReader(conexao.getInputStream()));
			entrada.readLine();				
		}catch(IOException e){
			System.out.println("IOException"+e);
		}finally{
			try {
				conexao.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
F

alguem pode me dar alguma dica ou opniao

ViniGodoy

É assim mesmo. Agora só falta você melhorar o protocolo de comunicação e colocar mensagens que façam mais sentido para a autenticação, troca de dados e desconexão.

F

certo… obrigado vini por ter me ajudado
atE+

V

Pessoal, estou fazendo uma aplicação parecida, onde tenho apenas um cliente que faz várias requisições ao servidor. Pergunta: No servidor devo abrir uma thread para a conexão do cliente, mas na classe cliente, devo abrir uma thread para cada requisição feita ao servidor? :?:

Criado 14 de janeiro de 2011
Ultima resposta 3 de ago. de 2012
Respostas 13
Participantes 4