O que está acontecendo com esses Sockets?

7 respostas
N

O JFrame do Cliente fica travado, não consigo acessá-lo. Só consigo destravar a tela do Cliente quando o JFrame do Servidor é fechado…
Porque acontece isso?

Servidor:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class Servidor implements ActionListener, KeyListener {
    
   private JFrame janela = new JFrame("Servidor");
   private String nome;
   private JPanel conversaPanel = new JPanel();
   private JPanel mensagemPanel = new JPanel();
   private JTextArea conversaTextArea = new JTextArea(41, 75);
   private JScrollPane conversaScrollPane = new JScrollPane(conversaTextArea);
   private JTextField mensagemTextField = new JTextField(70);
   private JButton mensagemButton = new JButton("Enviar Mensagem");
   // Rede.
   private ServerSocket serverSocket = null; 
   private Socket socket = null;
   private BufferedReader entrada;
   private PrintStream saida;
   
   /** Creates a new instance of Servidor */
   public Servidor(String nome) {
   
      this.nome = nome;
      janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      conversaPanel.add(conversaScrollPane);
      mensagemPanel.add(mensagemTextField);
      mensagemPanel.add(mensagemButton);
      janela.add(conversaPanel, BorderLayout.WEST);
      janela.add(mensagemPanel, BorderLayout.SOUTH);
      janela.setExtendedState(JFrame.MAXIMIZED_BOTH);
      janela.setVisible(true);
      // Listeners.
      mensagemButton.addActionListener(this);
      mensagemTextField.addKeyListener(this);
      
      try {
         serverSocket = new ServerSocket(1000); 
         socket = serverSocket.accept();
         entrada = new BufferedReader(new InputStreamReader(socket.getInputStream()));
         saida = new PrintStream(socket.getOutputStream());
         while(true) {
            String s = entrada.readLine();
            if(! s.trim().equals(""))
               conversaTextArea.setText(conversaTextArea.getText() + "\n" + s);
         }
      }
      catch(IOException ioe) {
         System.out.println(ioe);    
      }
   
   }
   
   public void keyPressed(KeyEvent ke) {
   
      if(ke.getKeyCode() == KeyEvent.VK_ENTER && ! mensagemTextField.getText().trim().equals("")) {
         conversaTextArea.setText(conversaTextArea.getText() + "\n" + nome + " : " + mensagemTextField.getText());    
         saida.println(nome + " : " + mensagemTextField.getText());
         mensagemTextField.setText("");
      }
   
   }
   
   public void actionPerformed(ActionEvent ae) {
       
      Object objeto = ae.getSource();   
      if(objeto == mensagemButton && ! mensagemTextField.getText().trim().equals("")) {
         conversaTextArea.setText(conversaTextArea.getText() + "\n" + nome + " digitou: " + mensagemTextField.getText());    
         saida.println(nome + " : " + mensagemTextField.getText());
         mensagemTextField.setText("");
      }
   
   }
    
   public static void main(String[] args) {
      Servidor s = new Servidor("Servidor");
   }

}

Cliente. Uma tela de login pede o IP do Servidor e o apelido do usuário. Com esses dois argumentos é criado o objeto Cliente.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class Cliente implements ActionListener, KeyListener {
    
   private JFrame janela = new JFrame("Cliente");
   private JPanel conversaPanel = new JPanel();
   private JPanel mensagemPanel = new JPanel();
   private JTextArea conversaTextArea = new JTextArea(41, 75);
   private JScrollPane conversaScrollPane = new JScrollPane(conversaTextArea);
   private JTextField mensagemTextField = new JTextField(70);
   private JButton mensagemButton = new JButton("Enviar Mensagem");
   // Rede.
   private Socket socket = null; 
   private BufferedReader entrada;
   private PrintStream saida;
   private String nome;
   private String ip;
      
   /** Creates a new instance of Cliente */
   public Cliente(String ip, String nome) {
   
      this.nome = nome;
      janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      janela.setLayout(new FlowLayout());
      conversaPanel.add(conversaScrollPane);
      mensagemPanel.add(mensagemTextField);
      mensagemPanel.add(mensagemButton);
      janela.add(conversaPanel, BorderLayout.WEST);
      janela.add(mensagemPanel, BorderLayout.SOUTH);
      janela.setExtendedState(JFrame.MAXIMIZED_BOTH);
      janela.setVisible(true);
      // Listeners.
      mensagemButton.addActionListener(this);
      mensagemTextField.addKeyListener(this);
      
      try {
         socket = new Socket(ip, 1000);
         entrada = new BufferedReader(new InputStreamReader(socket.getInputStream()));
         saida = new PrintStream(socket.getOutputStream());
         while(true) {
            String s = entrada.readLine(); 
            if(! s.trim().equals(""))               
               conversaTextArea.setText(conversaTextArea.getText() + "\n" + s);
         }
      }
      catch(IOException ioe) {
         System.out.println(ioe);    
      }
   
   }
   
   public void keyPressed(KeyEvent ke) {
   
      if(ke.getKeyCode() == KeyEvent.VK_ENTER && ! mensagemTextField.getText().trim().equals("")) {
         conversaTextArea.setText(conversaTextArea.getText() + "\n" + nome + " : " + mensagemTextField.getText());    
         saida.println(nome + " : " + mensagemTextField.getText());
         mensagemTextField.setText("");
      }
   
   }
   
   public void actionPerformed(ActionEvent ae) {
       
      Object objeto = ae.getSource();   
      if(objeto == mensagemButton && ! mensagemTextField.getText().trim().equals("")) {
         conversaTextArea.setText(conversaTextArea.getText() + "\n" + nome + " digitou: " + mensagemTextField.getText());    
         saida.println(nome + " : " + mensagemTextField.getText());
         mensagemTextField.setText("");
      }
   
   }
   
}

Qualquer ajuda, será bem vinda.

7 Respostas

S

Imagino que o problema seja esse while(true) que você utiliza.
Acho que você vai ter que usar threads para resolver.

N

SdRuboW, você compilou as classes e verificou como ficam? Qualquer coisa me avisa. Eu acho que Threads só ficará viável quando mais de duas pessoas estiverem conversando, assim o servidor teria que lidar com duas requisições. Mas eu creio que tem como consertar esse bug sem o uso de Threads, só não sei como ainda.

Obrigado e ainda estou buscando soluções!

J

Na realidade você tem que usar Threads, pois você está travando a unica thread que está em execução (a main), aí não fica nenhuma pra cuidar da atualização da interface.

Coloque o codigo de comunicação com os sockets em uma Thread.

N

jairelton, se é assim, porque somente o cliente trava e o servidor não?

R

Exetamente ele trava por nao usar 2 threads
o servidor roda primeiro e fica rodando e nunca o cliente roda.
vc precisa de thread pois sem ela vc so executa uma pilha de execução

se precisar de como faz threads nos ajudamos.

até mais

J

Na realidade o problema é que você deve estar instanciando as duas classes dentro do mesmo main(), como uma aplicação só, isso vai fazer com que a Thread fique ocupada com o servidor e o cliente não seja atualizado…

Simplesmente coloque um metodo main() na classe Cliente, isso vai criar Threads diferentes (como aplicações diferentes nesse caso), para cada um.

N

Jairelton, a classe Cliente é executada separadamente da classe Servidor.
E mesmo executando em dois computadores diferentes em uma rede local ou pela internet, o problema do cliente travado permanece…
Aqui está a classe que instancia o Cliente, ela faz parte do mesmo .jar:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TelaLogin implements ActionListener {
    
   private JFrame janela = new JFrame("Apelido");
   private JLabel ipLabel = new JLabel("IP servidor: ");
   private JLabel apelidoLabel = new JLabel("Apelido: ");
   private JTextField ipTextField = new JTextField(15);
   private JTextField apelidoTextField = new JTextField(10);
   private JButton okButton = new JButton("OK");
   private String ip;
       
   /** Creates a new instance of TelaLogin */
   public TelaLogin() {
      
      janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      janela.setLayout(new FlowLayout());
      janela.add(ipLabel);
      janela.add(ipTextField);
      janela.add(apelidoLabel);
      janela.add(apelidoTextField);
      janela.add(okButton);
      janela.pack();
      janela.setResizable(false);
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
      int largura = d.width;
      int altura = d.height;
      janela.setBounds((largura - janela.getWidth()) / 2, (altura - janela.getHeight()) / 2, janela.getWidth(), janela.getHeight());
      janela.setVisible(true);
      // Listeners.
      okButton.addActionListener(this);
         
   }
   
   public void actionPerformed(ActionEvent ae) {
       
      Object objeto = ae.getSource();
      if(objeto == okButton && ! ipTextField.getText().trim().equals("") && ! apelidoTextField.getText().trim().equals("")) {
         janela.setVisible(false);
         Cliente cliente = new Cliente(ip, apelidoTextField.getText());
      }
   
   }
   
   public static void main(String[] args) {
      TelaLogin tl = new TelaLogin();
   }
    
}

Sugestões ainda serão aceitas.
Obrigado.

Criado 12 de janeiro de 2008
Ultima resposta 15 de jan. de 2008
Respostas 7
Participantes 4