es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La clase Java Thread no está pasando por el bucle.

Estoy tratando de construir un servidor usando la clase ServerSocket en Java y haciendo una aplicación como Discord donde lanzas el programa ServeurDialogue en la shell y te conectas a él a través de un cliente telnet usando la dirección local y el puerto: 2021 y para eso, utilizo dos hilos, uno para permanecer en modo de escucha donde acepta nuevos clientes y los almacena en una matriz, y el segundo hilo envía un mensaje cada vez que un cliente envía un mensaje, lo transfiere al resto de los clientes.

Ahora mi problema es que el hilo que he llamado sendToAll no está pasando por el bucle for

Thread sendToAll = new Thread(){
        public void run(){
          String tmpMsg;
          while(true){
            try{
              for (ThreadClient c : clients) {
                if (c.getPendingMsg()) {
                  for (ThreadClient cl : clients) {
                    if (c != cl) {
                      cl.getSocket().getOutputStream().write(c.getMessage().getBytes());

                }
              }

            }

          }
        } catch(IOException e){
          System.out.println(e);
          }
      }

    }
  };


Aunque en mi segundo hilo connectionThread tengo el mismo bucle pero recorre los clientes y envía el mensaje nuevo cliente sin ningún problema

Thread connectionThread = new Thread(){
        public void run(){
          Socket socketRecu;
          while (true){
            System.out.println("Server is waiting for a connection...");

        try{
          socketRecu = serveur.accept();
          System.out.println("Client Accepted!\nAddress: "+ socketRecu.getLocalAddress() + "\nPort: "+ socketRecu.getPort());
          socketRecu.getOutputStream().write("Welcome in my Server!\n".getBytes());

          ThreadClient client = new ThreadClient(socketRecu);

          for (ThreadClient c : clients) {
            c.getSocket().getOutputStream().write("new Client\n".getBytes());

          }

          clients.add(client);
          client.start();

        } catch(IOException e){
          System.out.println(e);
        }
      }
    }
  };


Entonces, ¿por qué el segundo hilo atraviesa el bucle como debería hacerlo, pero no en el primer hilo?

Para su información: ThreadClient es una clase que hice que extiende la clase Thread y sigue escuchando si el cliente desea enviar el mensaje.

Aquí debajo encontrarás las dos clases completas que necesitas.

los archivos:

ServeurDialogue.java:

import java.net.ServerSocket;
import java.io.IOException;
import java.net.Socket;
import java.lang.Thread;
import java.util.Arrays;
import java.util.ArrayList;
import util.ThreadClient;
import util.ServerThread;

public class ServeurDialogue {

private static final int PORT = 2021;

public static void main(String[] args) {

  try{
  ServerSocket serveur = new ServerSocket(PORT);
  ArrayList<ThreadClient> clients = new ArrayList<>();



  Thread sendToAll = new Thread(){
    public void run(){
      String tmpMsg;
      while(true){
        try{
          for (ThreadClient c : clients) {
            if (c.getPendingMsg()) {
              for (ThreadClient cl : clients) {
                if (c != cl) {
                  cl.getSocket().getOutputStream().write(c.getMessage().getBytes());

                }
              }

            }

          }
        } catch(IOException e){
          System.out.println(e);
          }
      }

    }
  };
    sendToAll.start();

  Thread connectionThread = new Thread(){
    public void run(){
      Socket socketRecu;
      while (true){
        System.out.println("Server is waiting for a connection...");

        try{
          socketRecu = serveur.accept();
          System.out.println("Client Accepted!\nAddress: "+ socketRecu.getLocalAddress() + "\nPort: "+ socketRecu.getPort());
          socketRecu.getOutputStream().write("Welcome in my Server!\n".getBytes());

          ThreadClient client = new ThreadClient(socketRecu);

          for (ThreadClient c : clients) {
            c.getSocket().getOutputStream().write("new Client\n".getBytes());

          }

          clients.add(client);
          client.start();

        } catch(IOException e){
          System.out.println(e);
        }
      }
    }
  };
  connectionThread.start();



  } catch(IOException e){
    System.out.println(e);
  }


}


}

ThreadClient.java:

package util;
import java.lang.Thread;
import java.net.Socket;
import java.lang.Thread;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.IOException;

public class ThreadClient extends Thread {

private Socket socket;
  private byte[] buffer = new byte[1024];
  private boolean pendingMsg;
  private String message;
  public ThreadClient(Socket socket){
    super();
    this.socket = socket;
    this.pendingMsg = false;
  }

public Socket getSocket(){
      return this.socket;
  }
  public boolean getPendingMsg(){
    return this.pendingMsg;
  }
  public byte[] getBuffer(){
    return this.buffer;
  }
  public String getMessage(){
    this.pendingMsg = false;
    return this.message;
  }
  public void sendMessage(){
    this.pendingMsg = true;
    this.message = new String(this.buffer);
  }
  public void run(){

while(true){
  Arrays.fill(this.buffer, (byte) 0);
  try{
    this.socket.getInputStream().read(this.buffer);
    this.sendMessage();
    System.out.print("Message received: "+ this.message);

  } catch(IOException e) {System.out.println(e);}

}


}

}

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Es probable que el problema esté relacionado con la forma en que estás accediendo al array de clients en el hilo de sendToAll. Estás accediendo al array en un bucle, pero no estás sincronizando el acceso al array. Esto significa que el array puede ser modificado por otro hilo mientras lo estás recorriendo, lo que puede llevar a un comportamiento inesperado. Para solucionar esto, debes usar la palabra clave synchronized al acceder al array, o usar Collections.synchronizedList() para asegurarte de que el array sea seguro para hilos.

Comments are closed.