В принципе у вас есть работа однопоточного сервера (что означает, что он может принимать только одно клиентское соединение одновременно).Основная проблема заключается в том, что вы слишком усложнили способ получения соединения.
Вы можете упростить свой текущий код, решив задачу, переместив сокет клиентского соединения и считыватели в локальную область, и напрямую работая с сокетом.
public void serverConnect() throws IOException {
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} catch (IOException ignore) {
} finally {
socket.close();
}
}
}
Как видите, вам не нужно удерживать сокет за пределами считывания отправленного значения.Если вы ожидаете только одну строку данных от клиента, вы также должны закрыть сокет, в противном случае клиент может удерживать сервер в качестве заложника, не отправляя никаких данных до тех пор, пока не истечет время ожидания сокета.
В дополнение к этому вытакже хочу обернуть код внутри цикла while блоком try / catch, чтобы исключить завершение работы сервера.
Как я уже упоминал во вводном абзаце, этот код работает как однопоточный сервер и может отвечать толькона один запрос за раз.Если вы хотите принимать и обрабатывать несколько запросов, вам нужно создать новый поток для обработки ответа.Я бы порекомендовал построить ваш код, как показано ниже, но для краткости вы можете сделать что-то вроде следующего:
public void serverConnect() throws IOException {
int MAX_WORKERS = 100;
ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
ServerSocket listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
service.submit(() -> {
System.out.println("Client is connected");
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} finally {
socket.close();
}
} catch (Throwable ignore) {
}
});
}
}
Итак, все, что происходит выше, это то, что мы создаем пул потоков из 100 потоков, используя ExecutorService
.Теоретически это означает, что мы можем принять 100 одновременных соединений.
Когда соединение принято, мы передаем сокет и рабочий код потоку, что означает, что основной поток может вернуться к прослушиванию новых соединений.