web-dev-qa-db-fra.com

Créer le ServerSocket dans un thread séparé?

J'ai un problème avec l'utilisation d'un ServerSocket dans mon application.

Je crée le ServerSocket dans le constructeur de mon application. Le constructeur du socket appelle la méthode accept() pour attendre qu'un client se connecte.

Le problème est que la méthode accept() gèle toute mon application jusqu'à ce qu'un client se connecte. Je voudrais donc demander s'il existe une alternative à la création de l'ensemble ServerSocket dans un thread séparé, que le constructeur de la ServerSocket et sa méthode accept() est appelé à côté de mon application principale?

Éditer:

Merci à Olivier pour les conseils, mettre le .accept dans un exécutable et créer un pool de threads pour gérer les connexions client.

C'est mon code en ce moment:

  public void start(){

      final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

      Runnable serverTask = new Runnable() {
          @Override
          public void run() {

              try {
                  serverSocket = new ServerSocket(port);

                  while (true) {
                      Socket clientSocket = serverSocket.accept();
                      objectout = new ObjectOutputStream(clientSocket.getOutputStream());
                      clientProcessingPool.submit(new ClientTask(clientSocket,objectout)); 
                  }
              } catch (IOException e) {
                  System.err.println("Accept failed.");
              }

          }
      };

Tout va bien! Merci!

21
Chocolate

Habituellement, j'utilise N + 1 threads pour cela: un pour le ServerSocket, pour éviter de bloquer toute l'application en attente d'un client pour se connecter; et N threads pour traiter les demandes du client, N étant la taille du pool de threads (je recommande d'utiliser un pool de threads plutôt que de créer un nouveau thread par client).

Voici un exemple (juste codé, vous voudrez peut-être avoir une meilleure gestion des exceptions et autres, mais ceci est un exemple de travail minimal)

public class Server {

    public static void main(String[] args) {
        new Server().startServer();
    }

    public void startServer() {
        final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

        Runnable serverTask = new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocket serverSocket = new ServerSocket(8000);
                    System.out.println("Waiting for clients to connect...");
                    while (true) {
                        Socket clientSocket = serverSocket.accept();
                        clientProcessingPool.submit(new ClientTask(clientSocket));
                    }
                } catch (IOException e) {
                    System.err.println("Unable to process client request");
                    e.printStackTrace();
                }
            }
        };
        Thread serverThread = new Thread(serverTask);
        serverThread.start();

    }

    private class ClientTask implements Runnable {
        private final Socket clientSocket;

        private ClientTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            System.out.println("Got a client !");

            // Do whatever required to process the client's request

            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
42
Olivier Croisier