Skip to content

Commit a1f8e05

Browse files
authored
I will come to you shortly, if the Lord wills
But I will come to you shortly, if the Lord wills, and will know, not the speech of them who are puffed up, but the power (1Cor 4:19)
1 parent fb48b88 commit a1f8e05

1 file changed

Lines changed: 138 additions & 0 deletions

File tree

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
2+
//But I will come to you shortly, if the Lord wills, and will know, not the speech of them who are puffed up, but the power (1Cor 4:19)
3+
4+
package com.javarush.task.task30.task3008;
5+
6+
import java.util.Map;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.io.*;
9+
import java.net.ServerSocket;
10+
import java.net.Socket;
11+
12+
13+
public class Server {
14+
15+
private static Map<String, Connection> connectionMap = new ConcurrentHashMap<>();
16+
17+
public static void sendBroadcastMessage(Message message) {
18+
for (Connection connection : connectionMap.values()) {
19+
try {
20+
connection.send(message);
21+
} catch (IOException e) {
22+
ConsoleHelper.writeMessage("Something wrong with sending message...");
23+
}
24+
}
25+
}
26+
27+
public static void main(String[] args) {
28+
ConsoleHelper.writeMessage("Please, input server port: ");
29+
try (ServerSocket serverSocket = new ServerSocket(ConsoleHelper.readInt())) {
30+
ConsoleHelper.writeMessage("Server starting...");
31+
while (true) {
32+
new Handler(serverSocket.accept()).start();
33+
}
34+
} catch (Exception e) {
35+
ConsoleHelper.writeMessage("Error, server socket was closed.");
36+
}
37+
}
38+
39+
private static class Handler extends Thread {
40+
private Socket socket;
41+
42+
public Handler(Socket socket) {
43+
this.socket = socket;
44+
}
45+
46+
public void run() {
47+
48+
if (socket != null && socket.getRemoteSocketAddress() != null) {
49+
ConsoleHelper.writeMessage("Established a new connection to remote-socket, address: " + socket.getRemoteSocketAddress());
50+
}
51+
String userName = null;
52+
53+
try (Connection connection = new Connection(socket)) {
54+
55+
userName = serverHandshake(connection);
56+
sendBroadcastMessage(new Message(MessageType.USER_ADDED, userName));
57+
sendListOfUsers(connection, userName);
58+
serverMainLoop(connection, userName);
59+
} catch (IOException | ClassNotFoundException e) {
60+
ConsoleHelper.writeMessage("error of remote socket address data exchange");
61+
} finally {
62+
if (userName != null) {
63+
connectionMap.remove(userName);
64+
sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName));
65+
}
66+
ConsoleHelper.writeMessage("Closed connection to remote-socket, address: "); // + socketAddress);
67+
}
68+
}
69+
70+
private String serverHandshake(Connection connection) throws IOException, ClassNotFoundException {
71+
while (true) {
72+
connection.send(new Message(MessageType.NAME_REQUEST));
73+
Message answer = connection.receive();
74+
75+
if (answer.getType() == MessageType.USER_NAME) {
76+
77+
if (!answer.getData().isEmpty()) {
78+
if (!connectionMap.containsKey(answer.getData())) {
79+
connectionMap.put(answer.getData(), connection);
80+
connection.send(new Message(MessageType.NAME_ACCEPTED));
81+
return answer.getData();
82+
}
83+
}
84+
}
85+
}
86+
}
87+
88+
private void sendListOfUsers(Connection connection, String userName) throws IOException {
89+
for (Map.Entry<String, Connection> entry : connectionMap.entrySet()) {
90+
if (!entry.getKey().equals(userName)) {
91+
connection.send(new Message(MessageType.USER_ADDED, entry.getKey()));
92+
}
93+
}
94+
}
95+
96+
private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException {
97+
while (true) {
98+
Message message = connection.receive();
99+
if (message != null && message.getType() == MessageType.TEXT) {
100+
sendBroadcastMessage(new Message(MessageType.TEXT, userName + ": " + message.getData()));
101+
} else {
102+
ConsoleHelper.writeMessage("Error: something wrong");
103+
}
104+
}
105+
}
106+
}
107+
}
108+
109+
/*
110+
Чат (11)
111+
Пришло время написать главный метод класса Handler, который будет вызывать все
112+
вспомогательные методы, написанные ранее. Реализуем метод void run() в классе Handler.
113+
114+
Он должен:
115+
1. Выводить сообщение, что установлено новое соединение с удаленным адресом, который можно получить с помощью метода getRemoteSocketAddress.
116+
2. Создавать Connection, используя поле socket.
117+
3. Вызывать метод, реализующий рукопожатие с клиентом, сохраняя имя нового клиента.
118+
4. Рассылать всем участникам чата информацию об имени присоединившегося участника (сообщение с типом USER_ADDED). Подумай, какой метод подойдет для этого лучше всего.
119+
5. Сообщать новому участнику о существующих участниках.
120+
6. Запускать главный цикл обработки сообщений сервером.
121+
7. Обеспечить закрытие соединения при возникновении исключения.
122+
8. Отловить все исключения типа IOException и ClassNotFoundException, вывести в консоль информацию, что произошла ошибка при обмене данными с удаленным адресом.
123+
9. После того как все исключения обработаны, если п.11.3 отработал и возвратил нам имя, мы должны удалить запись для этого имени из connectionMap и разослать всем остальным участникам сообщение с типом USER_REMOVED и сохраненным именем.
124+
10. Последнее, что нужно сделать в методе run() – вывести сообщение, информирующее что соединение с удаленным адресом закрыто.
125+
126+
Наш сервер полностью готов. Попробуй его запустить.
127+
128+
129+
Требования:
130+
1. Метод run должен выводить на экран сообщение о том, что было установлено соединение с удаленным адресом (используя метод getRemoteSocketAddress).
131+
2. Метод run должен создавать новое соединение (connection) используя в качестве параметра поле socket.
132+
3. Метод run должен вызывать метод serverHandshake используя в качестве параметра только что созданное соединение; результатом будет имя пользователя (userName).
133+
4. Метод run должен вызывать метод sendBroadcastMessage используя в качестве параметра новое сообщение (MessageType.USER_ADDED, userName).
134+
5. Метод run должен вызывать метод sendListOfUsers используя в качестве параметров connection и userName.
135+
6. Метод run должен вызывать метод serverMainLoop используя в качестве параметров connection и userName.
136+
7. Прежде чем завершиться, метод run должен удалять из connectionMap запись соответствующую userName, и отправлять всем участникам чата сообщение о том, что текущий пользователь был удален.
137+
8. Метод run должен корректно обрабатывать исключения IOException и ClassNotFoundException.
138+
*/

0 commit comments

Comments
 (0)