Есть два блока кода с по сути одинаковым заданием для каждого:
1. Проверить тип сообщения;
2. Если тип соответствует обрабатываемым - принять меры;
3. Если тип не соответствует обрабатываемым - бросить исключение и закончить цикл.
*на реализацию обработки каждого типа внимание не обращаем, она валидатору нравится.
Первый блок выполнен через if-else и он успешно проходит валидацию.
Второй выполнен через switch-case и валидацию пройти не может. При замене на else-if он ее успешно прошел.
При этом в условии задачи есть прямой намек на необходимость использования именно switch-case.
Посему хочу разобраться что я упустил.
Я изначально пробовал:
1. Бросать исключение в default: блоке;
2. Бросать исключение без дополнительных проверок;
3. Заводить отдельную переменную под проверяемый тип;
4. И даже вместо break использовать continue.
Ничто из этого ситуацию не меняет.
/**
* Блок первый, тестирование проходит.
*/
protected void clientHandshake() throws IOException, ClassNotFoundException {
while(true){
Message serverMessage = connection.receive();
if (serverMessage.getType() == MessageType.NAME_REQUEST) {
connection.send(new Message(MessageType.USER_NAME, getUserName()));
} else if (serverMessage.getType() == MessageType.NAME_ACCEPTED) {
notifyConnectionStatusChanged(true);
break;
} else {
throw new IOException("Unexpected MessageType");
}
}
}
/**
* Блок второй, тестирование не проходит.
*/
protected void clientMainLoop() throws IOException, ClassNotFoundException {
while (true) {
Message serverMessage = connection.receive();
switch (serverMessage.getType()) {
case TEXT: {
processIncomingMessage(serverMessage.getData());
break;
}
case USER_ADDED: {
informAboutAddingNewUser(serverMessage.getData());
break;
}
case USER_REMOVED: {
informAboutDeletingNewUser(serverMessage.getData());
break;
}
}
if (serverMessage.getType() != MessageType.TEXT &&
serverMessage.getType() != MessageType.USER_ADDED &&
serverMessage.getType() != MessageType.USER_REMOVED) {
throw new IOException("Unexpected MessageType");
}
}
}package com.javarush.task.task30.task3008;
/**
* Добавь:
*
* 1)В класс Server приватный статический вложенный класс Handler, унаследованный от Thread.
*
* 2)В класс Handler поле socket типа Socket.
*
* 3)В класс Handler конструктор, принимающий в качестве параметра Socket и инициализирующий им
* соответствующее поле класса.
*
* 4)Метод main класса Server, должен:
* а) Запрашивать порт сервера, используя ConsoleHelper.
* б) Создавать серверный сокет java.net.ServerSocket, используя порт из предыдущего пункта.
* в) Выводить сообщение, что сервер запущен.
* г) В бесконечном цикле слушать и принимать входящие сокетные соединения только что созданного
* серверного сокета.
* д) Создавать и запускать новый поток Handler, передавая в конструктор сокет из предыдущего пункта.
* е) После создания потока обработчика Handler переходить на новый шаг цикла.
* ж) Предусмотреть закрытие серверного сокета в случае возникновения исключения.
* з) Если исключение Exception все же произошло, поймать его и вывести сообщение
* об ошибке.
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.*;
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;
}
public void run(){
ConsoleHelper.writeMessage("Connected: " + socket.getRemoteSocketAddress());
try {
Connection connection = new Connection(socket);
try {
String userName = serverHandshake(connection);
try {
sendBroadcastMessage(new Message(MessageType.USER_ADDED, userName));
sendListOfUsers(connection, userName);
serverMainLoop(connection, userName);
} catch (Exception lifeCycleException) {
ConsoleHelper.writeMessage("Exception has been thrown... terminating connection...");
try {
connection.close();
} catch (IOException cantCloseException) {}
} finally {
connectionMap.remove(userName);
sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName));
}
} catch (Exception nameException) {
ConsoleHelper.writeMessage("Handshake failed...");
try {
connection.close();
} catch (IOException cantCloseException) {}
}
} catch (Exception connectionException) {
ConsoleHelper.writeMessage("Failed to create connection...");
}
ConsoleHelper.writeMessage("...Connection terminated...");
}
private String serverHandshake(Connection connection) throws IOException, ClassNotFoundException {
while (true) {
connection.send(new Message(MessageType.NAME_REQUEST));
Message userRespond = connection.receive();
MessageType respondType = userRespond.getType();
String userName = userRespond.getData();
if (respondType != MessageType.USER_NAME) continue;
if (userName == null || userName.isEmpty() || connectionMap.containsKey(userName)) continue;
connectionMap.put(userName, connection);
connection.send(new Message(MessageType.NAME_ACCEPTED));
return userName;
}
}
private void sendListOfUsers(Connection connection, String userName) throws IOException {
for (String connectedUser : connectionMap.keySet()) {
if (connectedUser.equals(userName)) continue;
connection.send(new Message(MessageType.USER_ADDED, connectedUser));
}
}
private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException {
while (true) {
Message receivedMessage = connection.receive();
if (receivedMessage.getType() == MessageType.TEXT) {
Message responseMessage = new Message(MessageType.TEXT, String.format("%s: %s", userName, receivedMessage.getData()));
sendBroadcastMessage(responseMessage);
} else ConsoleHelper.writeMessage("Wrong message type");
}
}
}
public static void main(String[] args){
try {
ServerSocket sSocket = new ServerSocket(ConsoleHelper.readInt());
ConsoleHelper.writeMessage("Server is running.");
while (true) {
try {
Handler handler = new Handler(sSocket.accept());
handler.start();
} catch(Exception e) {
sSocket.close();
ConsoleHelper.writeMessage(e.getMessage());
break;
}
}
} catch(Exception e){
ConsoleHelper.writeMessage(e.getMessage());
}
}
public static void sendBroadcastMessage(Message message){
try{
for (Connection connection : connectionMap.values()) {
connection.send(message);
}
} catch (IOException e) {
ConsoleHelper.writeMessage("Message received... a-a-and... its gone.");
}
}
}