Подтвердить что ты не робот

Создание ServerSocket в отдельном потоке?

У меня есть проблема с использованием ServerSocket в моем приложении.

Я создаю ServerSocket в конструкторе моего приложения. Конструктор сокета вызывает метод accept() для ожидания подключения клиента.

Проблема заключается в том, что метод accept() замораживает все мое приложение до тех пор, пока клиент не подключится. Поэтому я хотел бы спросить, есть ли альтернатива созданию всего ServerSocket в отдельном потоке, что конструктор метода ServerSocket и его accept() вызывается рядом с моим основным приложением?

Edit:

Спасибо Olivier за совет, положив .accept в runnable и создав threadpool для обработки клиентских соединений.

Вот мой код прямо сейчас:

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

          }
      };

Все отлично работает! Спасибо!

4b9b3361

Ответ 1

Обычно я использую N + 1 потоков для этого: один для ServerSocket, чтобы избежать блокировки всего приложения, ожидающего подключения клиента; и N потоков для обработки клиентских запросов, N - размер пула потоков (я рекомендую использовать пул потоков для создания нового потока для каждого клиента).

Вот пример (только что закодированный, вы можете иметь лучшее управление исключениями и т.д., но это минимальный рабочий пример)

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 request

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

}