Валидатор не даёт сведений для поиска недочётов, как обычно.
package com.javarush.task.task30.task3008;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**Сервер*/
public class Server {
//Имя клиента - Соединение с клиентом
private static Map<String, Connection> connectionMap = new ConcurrentHashMap<>();
/**Реализует протокол общения с клиентом*/
private static class Handler extends Thread {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
/**Реализует рукопожатие с клиентом
* @return Имя нового клиента*/
private String serverHandshake(Connection connection) throws IOException, ClassNotFoundException {
Message answer = null;
String name = null;
while (true) {
connection.send(new Message(MessageType.NAME_REQUEST));
answer = connection.receive();
name = answer.getData();
if (answer.getType() != MessageType.USER_NAME) continue;
if (name == null | name.isEmpty()) continue;
if (connectionMap.containsKey(name)) continue;
else break;
}
connectionMap.put(name, connection);
connection.send(new Message(MessageType.NAME_ACCEPTED));
return name;
}
/**Сообщает пользователям о подключении нового пользователя*/
private void sendListOfUsers(Connection connection, String userName) throws IOException {
for (Map.Entry<String, Connection> nameConnect: connectionMap.entrySet()) {
String name = nameConnect.getKey();
if (!name.equals(userName))
connection.send(new Message(MessageType.USER_ADDED, name));
}
}
/**Запускает цикл обработки сообщений*/
private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException {
while (true){
Message message = connection.receive();
if (message.getType() != MessageType.TEXT){
ConsoleHelper.writeMessage("Сообщение не является текстовым");
continue;
}
Message answer = new Message(MessageType.TEXT, userName + ": " + message.getData());
sendBroadcastMessage(message);
}
}
@Override
public void run() {
ConsoleHelper.writeMessage(socket.getRemoteSocketAddress().toString());
String userName = null;
try (Connection connection = new Connection(socket)){
userName = serverHandshake(connection);
sendListOfUsers(connection, userName);
serverMainLoop(connection, userName);
}catch (IOException | ClassNotFoundException e){
System.out.println("Произошла ошибка при обмене данными с удаленным адресом.");
}
if (userName != null) {
connectionMap.remove(userName);
sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName));
}
ConsoleHelper.writeMessage("Соединение с удаленным адресом закрыто.");
}
}
/**Отправялет всем пользователям сообщение*/
public static void sendBroadcastMessage(Message message) {
for (Map.Entry<String, Connection> nameConnect: connectionMap.entrySet()) {
try {
nameConnect.getValue().send(message);
}catch (IOException e){
System.out.println("Не удалось отправить сообщение");
}
}
}
public static void main(String[] args) {
ServerSocket serverSocket = null;
System.out.println("Сервер запущен");
try {
while (true){
serverSocket = new ServerSocket(ConsoleHelper.readInt());
Handler handler = new Handler(serverSocket.accept());
handler.start();
}
}catch (IOException e){
System.out.println("Ошибка соединения");
if (serverSocket != null)
try {
serverSocket.close();
}catch (IOException ex){}
}
}
}