La GUI de Java swing se congela

Estoy escribiendo una aplicación de GUI cliente / servidor Java utilizando sockets y aquí está el problema:

Tengo un botón para comenzar a escuchar un puerto específico:

botón acción Método informado

private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) { int port = Integer.parseInt(portTextfield.getText(), 10); try { socket.listen(port); } catch (IOException ex) { } } 

Aquí está el método socket.listen

 public static void listen() throws IOException { ServerSocket ss = new ServerSocket(port); while (true) new socket(ss.accept()); } 

La clase “socket” extiende “Thread”
Entonces, después de que ss.accept () devuelve un valor, crea una nueva instancia de socket en un hilo separado.

Después de hacer clic en el botón, la GUI se congela porque dentro del método socket.listen hay un ciclo infinito. ¿Cómo puedo evitar eso?

Tienes dos trampas en tu diseño:

  1. ss.accept() es una llamada de locking por lo que su UI se congelará hasta que haya una conexión entrante
  2. Nunca corra en bucles while(true) en el EDT.

En su lugar, haga lo siguiente:

  • Cuando se hace clic en el botón, crea un hilo que comenzará a escuchar las conexiones entrantes.
  • Siempre que tenga una conexión entrante, cree otra cadena que tome la conexión del cliente entrante y la maneje.

siempre y cuando tu

 new socket(ss.accept()); 

regresa inmediatamente, solo necesita cambiar su

 while (true) 

esto coloca el EDT (subproceso de envío de evento) en un bucle infinito y su GUI deja de responder. Por lo tanto, elimine esta línea.

Si no puede, utilice la clase SwingWorker ( http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List ) Cree una clase anidada que extensiones SwingWorker. Simplemente llame a swingWoker.execute (); (después de haber creado su objeto) en su método listenButtonActionPerformed (java.awt.event.ActionEvent evt) .

Vea el tutorial: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Nunca cree un nuevo hilo y ejecútelo desde el Swing EDT

Tendrá que usar Multi-Threading. Si yo fuera usted, separaría el código GUI y el código del servidor y cuando se presiona el botón, simplemente ejecuto el código del Servidor como un nuevo Subproceso.

Su código congela la GUI básicamente porque todos los eventos se ejecutan en el subproceso Event Dispatcher Thread (EDT), que es el hilo que se ocupa de todas las cosas de la GUI y los eventos respectivos. Si lo bloquea, lo detiene o lo lanza, afectará su rendimiento.

Mira esto: http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html

1) Si está escribiendo la aplicación GUI puede estar en Swing, nunca llame al método de locking en la cadena de distribución del evento o en el controlador de eventos. por ejemplo, si está leyendo un archivo o está abriendo una conexión de red cuando se hace clic en un botón, no haga eso en el método actionPerformed (), simplemente cree otro hilo de trabajo para hacer ese trabajo y regrese de actionPerformed (). esto mantendrá su GUI en buen estado, pero nuevamente depende del diseño si la operación es algo que requiere que el usuario espere antes que considerar el uso de invokeAndWait () para la actualización síncrona.

Uso de varios hilos: http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html

Prueba estos …

1. During getting the initial connection delay can occur, so first create and empty socket,then try to connect to the server.

  `Socket s = new Socket();` `s.connect(new InetSocketAddress("ip_addr",port_nos),1000);` 

2. And Secondly always keep the Non-UI work out of Your UI thread..

Aquí está mi ejemplo de servidor – Comunicación con el cliente.

Código del lado del cliente:

 public class ClientWala { public static void main(String[] args) throws Exception{ Boolean b = true; Socket s = new Socket(); s.connect(new InetSocketAddress("127.0.0.1", 4444),1000); System.out.println("connected: "+s.isConnected()); OutputStream output = s.getOutputStream(); PrintWriter pw = new PrintWriter(output,true); // to write data to server while(b){ if (!b){ System.exit(0); } else { pw.write(new Scanner(System.in).nextLine()); } } // to read data from server InputStream input = s.getInputStream(); InputStreamReader isr = new InputStreamReader(input); BufferedReader br = new BufferedReader(isr); String data = null; while ((data = br.readLine())!=null){ // Print it using sysout, or do whatever you want with the incoming data from server } } } 

Código del lado del servidor:

 import java.io.* import java.net.*; public class ServerTest { ServerSocket s; public void go() { try { s = new ServerSocket(44457); while (true) { Socket incoming = s.accept(); Thread t = new Thread(new MyCon(incoming)); t.start(); } } catch (IOException e) { e.printStackTrace(); } } class MyCon implements Runnable { Socket incoming; public MyCon(Socket incoming) { this.incoming = incoming; } @Override public void run() { try { PrintWriter pw = new PrintWriter(incoming.getOutputStream(), true); InputStreamReader isr = new InputStreamReader( incoming.getInputStream()); BufferedReader br = new BufferedReader(isr); String inp = null; boolean isDone = true; System.out.println("TYPE : BYE"); System.out.println(); while (isDone && ((inp = br.readLine()) != null)) { System.out.println(inp); if (inp.trim().equals("BYE")) { System.out .println("THANKS FOR CONNECTING...Bye for now"); isDone = false; s.close(); } } } catch (IOException e) { // TODO Auto-generated catch block try { s.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } } } public static void main(String[] args) { new ServerTest().go(); } }