esoe
2 years ago
21 changed files with 409 additions and 7 deletions
@ -1,2 +1,36 @@ |
|||||||
# SERVER : попытки настройки многофункционального сервера java |
# SERVER : попытки настройки многофункционального сервера java |
||||||
## Назначение |
## Назначение |
||||||
|
1. реализация exchange-сервиса |
||||||
|
- работа с HTTP протоколом (браузерным клиентом) |
||||||
|
- передача файлов от сервера в браузер |
||||||
|
- получение файлов от браузера на сервер |
||||||
|
2. реализация браузерного многопользовательского чата/форума |
||||||
|
3. реализация движка для управления динамическим контентом (лекции/презентации/графики обучения/) |
||||||
|
4. реализация движка для управения статическим контентом |
||||||
|
5. реализация интерфейса работы с базой данных (moodle) |
||||||
|
- заведение пользователей на платформу |
||||||
|
- выгрузка результатов тестирования пользователей |
||||||
|
6. реализация сервиса авторизации |
||||||
|
- на сервере |
||||||
|
- в сторонних приложениях |
||||||
|
7. |
||||||
|
## Реализация |
||||||
|
### Конфигурация сервера |
||||||
|
#### class Server |
||||||
|
Конструкторы: |
||||||
|
- Конструктор принимает номер порта, на котором запускется сервер |
||||||
|
Методы: |
||||||
|
start() |
||||||
|
down() |
||||||
|
|
||||||
|
Запускает ServerSocket на порту PORT |
||||||
|
|
||||||
|
|
||||||
|
> Сервер запускается в отдельном потоке, чтобы избежать блокирования приложения при реализации графического интерфейса. |
||||||
|
|
||||||
|
|
||||||
|
> Каждое соединение (Connection) запускается в отдельном потоке, чтобы обеспечить возможность многопользовательской реализации клиентского приложения |
||||||
|
|
||||||
|
> Каждый stream (поток пердачи данных) запускается в отдельном потоке, чтобы обеспечить возможность одновременно передавать, получать данные, а также сообщать серверу консольные команды. |
||||||
|
|
||||||
|
### Разбор HTTP запросов |
||||||
|
@ -0,0 +1,21 @@ |
|||||||
|
HTTP/1.1 200 OK |
||||||
|
|
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>molokoin.ru</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="header"> |
||||||
|
molokoin.ru |
||||||
|
</div> |
||||||
|
<div class="controls01"> |
||||||
|
<li><a href="http://molokoin.ru:3000/esoe">gitea</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru:8080">apache</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru/exchange">exchange</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru/hello">hello</a></li> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
Binary file not shown.
@ -0,0 +1,23 @@ |
|||||||
|
HTTP/1.1 200 OK |
||||||
|
|
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<title>send</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<form enctype="multipart/form-data" method="post"> |
||||||
|
<p><input type="file" name="f"> |
||||||
|
<input type="submit" value="push"></p> |
||||||
|
</form> |
||||||
|
<div class="downloads"> |
||||||
|
<a href="content\j130-lab1.pdf" download="j130-lab1.pdf">Download link + filename</a> |
||||||
|
</div> |
||||||
|
<div class="links"> |
||||||
|
<li><a href="http://molokoin.ru:3000/esoe">gitea</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru:8080">apache</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru/exchange">exchange</a></li> |
||||||
|
<li><a href="http://www.molokoin.ru/hello">hello</a></li> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,10 @@ |
|||||||
|
@startuml |
||||||
|
title "Classes to: Server" |
||||||
|
class Runner/'Инициализация и запуск компонентов программы'/ |
||||||
|
class Face extends Server |
||||||
|
class Server extends Thread |
||||||
|
class Connection extends Thread |
||||||
|
class ConsoleReader extends Thread |
||||||
|
class InputReader extends Thread |
||||||
|
class OutputWriter extends Thread |
||||||
|
@enduml |
@ -0,0 +1,9 @@ |
|||||||
|
@startuml |
||||||
|
title "Logic: Server" |
||||||
|
participant "Клиент" as client |
||||||
|
participant "Сервер" as server |
||||||
|
client --> server : "запрос" |
||||||
|
server --> server : "определение типа запроса\ntext, http ..." |
||||||
|
server --> server : "инициация соответствующего\n режима работы с клиентом" |
||||||
|
client <-- server : "ответ:\n- текст\n- http content\n- файл" |
||||||
|
@enduml |
@ -0,0 +1,69 @@ |
|||||||
|
package ru.molokoin; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.BufferedWriter; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.OutputStreamWriter; |
||||||
|
import java.net.Socket; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.Date; |
||||||
|
/** |
||||||
|
* Класс рализующий обработку подключения клиента к серверу |
||||||
|
* - Подключение вынесено в отдельный поток, чтобы обеспечить возможность подключения к серверу множества клиентов |
||||||
|
*/ |
||||||
|
public class Connection extends Thread{ |
||||||
|
public BufferedReader in; |
||||||
|
public BufferedWriter out; |
||||||
|
//public BufferedReader console;
|
||||||
|
|
||||||
|
public Connection(Socket socket) throws IOException{ |
||||||
|
System.out.println("Соединение с клиентом установлено ..."); |
||||||
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); |
||||||
|
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); |
||||||
|
//console = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
Thread threadConn = new Thread(this); |
||||||
|
threadConn.start(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Запуск потоков: |
||||||
|
* - получения сообщений, |
||||||
|
* - отправки сообщений |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void run(){ |
||||||
|
//new InputReader(this).start();//Запустили нить чтения сообщений от клиента
|
||||||
|
Thread threadReader = new Thread(new InputReader(this)); |
||||||
|
threadReader.start(); |
||||||
|
//new OutputWriter(this).start();//Запуск нити записи ответа клиенту
|
||||||
|
Thread threadWriter = new Thread(new OutputWriter(this)); |
||||||
|
threadWriter.start(); |
||||||
|
//new ConsoleReader(this).start; консоль должна управлять всем сервером, а не отдельным подключением
|
||||||
|
|
||||||
|
} |
||||||
|
/** |
||||||
|
* Отправка сообщений клиенту: |
||||||
|
* - для отправки даты и времени получения сервером сообщения |
||||||
|
* @param message |
||||||
|
*/ |
||||||
|
public void send (String message){ |
||||||
|
try { |
||||||
|
out.write(message + "\n"); |
||||||
|
out.flush(); |
||||||
|
} catch (IOException e) { |
||||||
|
System.out.println("Ошибка отправки сообщения: " + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* Получение текущего времени на сервере |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getTime(){ |
||||||
|
Date time; |
||||||
|
SimpleDateFormat pattern; |
||||||
|
time = new Date(); |
||||||
|
pattern = new SimpleDateFormat("HH:mm:ss"); |
||||||
|
return pattern.format(time); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package ru.molokoin; |
||||||
|
|
||||||
|
public class ConsoleReader { |
||||||
|
private Connection connection; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package ru.molokoin; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Нить чтения входящего от клиента потока данных |
||||||
|
*/ |
||||||
|
public class InputReader extends Thread{ |
||||||
|
static int index = 0;//порядковый номер обращения к серверу
|
||||||
|
private Connection connection; |
||||||
|
public InputReader(Connection connection){ |
||||||
|
this.connection = connection; |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void run(){ |
||||||
|
String line; |
||||||
|
|
||||||
|
Boolean f = true; |
||||||
|
try { |
||||||
|
while (!connection.in.ready()) ; |
||||||
|
index++; |
||||||
|
System.out.println("Номер запроса: " + index); |
||||||
|
StringBuilder header = new StringBuilder(); |
||||||
|
StringBuilder body = new StringBuilder(); |
||||||
|
Boolean isHeader = true; |
||||||
|
//Boolean isBody = false;
|
||||||
|
while (connection.in.ready()) { |
||||||
|
line = connection.in.readLine(); // ждем сообщения с сервера
|
||||||
|
if(isHeader){ |
||||||
|
if (line != null){ |
||||||
|
header.append(line); |
||||||
|
System.out.println("header: " + line); |
||||||
|
}else { |
||||||
|
isHeader = false; |
||||||
|
//isBody = true;
|
||||||
|
} |
||||||
|
} |
||||||
|
if(!isHeader){ |
||||||
|
if (line != null){ |
||||||
|
body.append(line); |
||||||
|
System.out.println("body: " + line); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* тут происходит: |
||||||
|
* - анализ поступающих от клиента сообщений |
||||||
|
* - инициация событий (методов), запрошенных клиентом |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (line.equals("stop")) {
|
||||||
|
// connection.down(); // харакири
|
||||||
|
// break; // выходим из цикла если пришло "stop"
|
||||||
|
// }
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException | NullPointerException e) { |
||||||
|
//connection.down();
|
||||||
|
System.out.println("InputReader() : Ошибка получения сообщения: " + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package ru.molokoin; |
||||||
|
|
||||||
|
import java.io.BufferedInputStream; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Обработка передачи данных клиенту |
||||||
|
*/ |
||||||
|
public class OutputWriter extends Thread{ |
||||||
|
private Connection connection; |
||||||
|
public OutputWriter(Connection connection){ |
||||||
|
this.connection = connection; |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void run(){ |
||||||
|
//чтение из файла, формирование сообщения для клиента
|
||||||
|
//String message = "";
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream("C:\\Users\\devuser\\Documents\\code\\Server\\content\\sample.http")) { |
||||||
|
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 10); |
||||||
|
int i; |
||||||
|
while((i = bufferedInputStream.read())!= -1){ |
||||||
|
char c = (char)i; |
||||||
|
connection.out.write(c); |
||||||
|
connection.out.flush(); |
||||||
|
String s = Character.toString(c); |
||||||
|
|
||||||
|
|
||||||
|
//message = message + (char)i;
|
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
//send(message);
|
||||||
|
// while(true){
|
||||||
|
|
||||||
|
//System.out.println("message: " + message);
|
||||||
|
//send(message);
|
||||||
|
// }
|
||||||
|
|
||||||
|
} |
||||||
|
/** |
||||||
|
* Отправка подготовленного сообщения-строки |
||||||
|
* @param message |
||||||
|
*/ |
||||||
|
public void send (String message){ |
||||||
|
try { |
||||||
|
connection.out.write(message + "\n"); |
||||||
|
connection.out.flush(); |
||||||
|
} catch (IOException e) { |
||||||
|
System.out.println("Ошибка отправки сообщения: " + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,7 +0,0 @@ |
|||||||
package ru.molokoin; |
|
||||||
|
|
||||||
public class Runner { |
|
||||||
public static void main(String[] args) { |
|
||||||
System.out.println("Запущен основной поток приложения: " + Thread.currentThread().getName()); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,50 @@ |
|||||||
|
package ru.molokoin; |
||||||
|
import java.io.IOException; |
||||||
|
import java.net.ServerSocket; |
||||||
|
import java.net.Socket; |
||||||
|
import java.util.LinkedList; |
||||||
|
|
||||||
|
/** |
||||||
|
* реализация основного потока сервера |
||||||
|
* - сервер вынесен в самостоятельный поток, чтобы не прерывать работу интерфейса |
||||||
|
*/ |
||||||
|
public class Server extends Thread{ |
||||||
|
private int port; |
||||||
|
private ServerSocket serverSocket; |
||||||
|
private LinkedList<Connection> connections = new LinkedList<Connection>(); |
||||||
|
|
||||||
|
public Server(int port){ |
||||||
|
this.port = port; |
||||||
|
} |
||||||
|
public static void main(String[] args) { |
||||||
|
new Server(10001).run(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
try (ServerSocket ss = new ServerSocket(port)) { |
||||||
|
serverSocket = ss; |
||||||
|
System.out.println("Сервер запущен ..."); |
||||||
|
while (true){ |
||||||
|
System.out.println("Сервер ожидает подключение клиента ..."); |
||||||
|
Socket socket = serverSocket.accept(); |
||||||
|
connections.add(new Connection(socket)); |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
System.out.println("Запуск сервера не удался ..."); |
||||||
|
System.out.println("Сообщение об ошибке: " + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* Остановка работы сервера |
||||||
|
*/ |
||||||
|
public void down(){ |
||||||
|
/** |
||||||
|
* В каждом соединении (connection) вызвать метод down() |
||||||
|
* - закрыть потоки in/out |
||||||
|
* - закрыть сокет подключения socket.close() |
||||||
|
* закрыть сервер |
||||||
|
* - serverSocket.close() |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
package ru.molokoin.faces.console; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
|
||||||
|
import ru.molokoin.Server; |
||||||
|
/** |
||||||
|
* Нить консольного интерфейса |
||||||
|
*/ |
||||||
|
public class Face extends Thread{ |
||||||
|
private Server server; |
||||||
|
private BufferedReader console; // поток чтения с консоли
|
||||||
|
|
||||||
|
public Face(Server server){ |
||||||
|
System.out.println("Инициализация консольного интерфейса управления сервером ..."); |
||||||
|
console = new BufferedReader(new InputStreamReader(System.in)); |
||||||
|
this.server = server; |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void run(){ |
||||||
|
System.out.println("Запуск консольного интерфейса управления сервером ..."); |
||||||
|
hello(); |
||||||
|
} |
||||||
|
private void hello() { |
||||||
|
System.out.println("Консольный интерфейс управления сервером запущен."); |
||||||
|
System.out.println(">>> СВЕДЕНИЯ О ПРОГРАММЕ <<<"); |
||||||
|
System.out.println("Для вызова помощи введите команду: \\help"); |
||||||
|
System.out.println("----------------------------"); |
||||||
|
help(); |
||||||
|
} |
||||||
|
private void help(){ |
||||||
|
System.out.println("Перечень доступных команд:"); |
||||||
|
System.out.println("перечень доступных команд: \\help"); |
||||||
|
System.out.println("запуск сервера: \\start"); |
||||||
|
System.out.println("остановка сервера: \\stop"); |
||||||
|
System.out.println("сводка по работе сервера: \\status"); |
||||||
|
listen(); |
||||||
|
} |
||||||
|
private void listen(){ |
||||||
|
System.out.println("Для получения помощи введите \\help"); |
||||||
|
System.out.println("Введите команду серверу:"); |
||||||
|
|
||||||
|
try{ |
||||||
|
String s = console.readLine(); |
||||||
|
switch (s) { |
||||||
|
case ("\\start"): |
||||||
|
Thread serverThread = new Thread(server); |
||||||
|
serverThread.start(); |
||||||
|
listen(); |
||||||
|
break; |
||||||
|
case ("\\stop"): |
||||||
|
server.down(); |
||||||
|
break; |
||||||
|
case ("\\quit"): |
||||||
|
System.exit(1); |
||||||
|
break; |
||||||
|
default: |
||||||
|
System.out.println("Указана не верная команда, попробуйте еще раз ..."); |
||||||
|
listen(); |
||||||
|
break; |
||||||
|
} |
||||||
|
}catch(IOException e){ |
||||||
|
System.out.println("Ошибка listen() чтения с консоли: " + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue