Search code examples
javamultithreadingserversocket

Creating the ServerSocket in a separate thread?


I have a problem with using a ServerSocket in my application.

I'm creating the ServerSocket in the constructor of my application. The constructor of the socket calls the accept() method to wait for a client to connect.

The problem is that the accept() method is freezing my whole application until a client connects. So I would like to ask if there's an alternative to creating the whole ServerSocket in a separate thread, that the constructor of the ServerSocket and its accept() method is called beside my main application?

Edit:

Thanks to Olivier for the advice, putting the .accept into a runnable and creating a threadpool to handle the clientconnections.

Thats my code right now:

  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.");
              }

          }
      };

Everythings running fine! Thanks!


Solution

  • Usually, I use N+1 threads for this : one for the ServerSocket, to avoid blocking the whole application waiting for a client to connect; and N threads to process the client's requests, N being the size of the thread pool (I recommend using a thread pool over creating a new thread per client).

    Here is an example (just coded it, you may want to have better exception management and such, but this is a minimal working example)

    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();
                }
            }
        }
    
    }