Skip to content

SENATOROVAI/ITMO_Lab6

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vehicle Collection — клиент-серверное приложение (ИТМО, лабораторная работа №6)

Распределённое приложение для управления коллекцией объектов Vehicle, разделённое на независимые клиент и сервер, которые обмениваются данными по сети через протокол UDP. Клиент принимает и разбирает команды пользователя, сервер хранит коллекцию в оперативной памяти, исполняет команды и сохраняет данные в файл формата CSV.


Цели работы

  • Перейти от монолитной консольной программы к архитектуре «клиент — сервер».
  • Реализовать сетевое взаимодействие на UDP с использованием как блокирующего (DatagramSocket на сервере), так и неблокирующего (DatagramChannel + Selector на клиенте) API.
  • Спроектировать прикладной протокол обмена сообщениями (Request / Response) поверх стандартной сериализации объектов Java.
  • Разделить ответственность между модулями: общий код, серверная логика, клиентская логика.
  • Обеспечить надёжную доставку: повторные попытки на клиенте и сборку больших ответов из частей (чанков).
  • Организовать хранение коллекции в файле и её загрузку при старте сервера.
  • Покрыть ключевую бизнес-логику модульными тестами (JUnit 5).

Предметная область

Хранимая сущность — Vehicle, объекты лежат в коллекции HashMap<Long, Vehicle> (ключ — key).

Поле Тип Ограничения
id long > 0, генерируется автоматически, уникален
name String не null, не пустая строка
coordinates Coordinates не null
creationDate LocalDate не null, генерируется автоматически
enginePower Float может быть null; если задано — > 0
type VehicleType не null: CAR, SUBMARINE, MOTORCYCLE, CHOPPER
fuelType FuelType не null: ELECTRICITY, DIESEL, MANPOWER, NUCLEAR

Coordinates: x (Double, не null, > -501), y (long). Vehicle неизменяем (final поля), реализует Comparable (сортировка по мощности → имени → id).


Технологический стек

Категория Технология
Язык Java 17
Сборка Maven (многомодульный проект, pom-агрегатор)
Сеть UDP: DatagramSocket (сервер), DatagramChannel + Selector (клиент)
Протокол обмена Сериализация объектов Java (ObjectOutputStream / ObjectInputStream)
Хранение Файл CSV
Логирование Log4j 2 (2.23.1)
Тестирование JUnit 5 (Jupiter 5.10.2)
Конфигурация Переменная окружения VEHICLE_COLLECTION_FILE

Архитектура и принятые решения

Многомодульная структура

Проект разбит на три Maven-модуля, что обеспечивает чёткое разделение ответственности и исключает зависимость клиента от внутренней логики сервера:

  • common — модели предметной области, протокол (Request/Response/CommandType) и утилита сериализации. Зависимость, общая для клиента и сервера.
  • server — приём UDP-пакетов, хранение коллекции, диспетчеризация команд, файловый ввод-вывод.
  • client — разбор пользовательского ввода, формирование запросов, отправка по сети и вывод ответов.

Сетевое взаимодействие

  • Сервер работает в одном потоке: блокирующий DatagramSocket с тайм-аутом SO_TIMEOUT = 300 мс, что позволяет в паузах между пакетами опрашивать собственную консоль (команды save, exit).
  • Клиент использует неблокирующий DatagramChannel + Selector. При отсутствии ответа выполняется до 5 повторных попыток с тайм-аутом 2 секунды — приложение устойчиво к потере пакетов и временной недоступности сервера.
  • Большие ответы (например, вывод всей коллекции) превышают размер одной датаграммы, поэтому делятся на чанки: каждый пакет несёт заголовок [всего чанков][индекс], а клиент собирает полное сообщение обратно.

Команды

Диспетчеризация команд построена на EnumMap<CommandType, CommandHandler> (CommandRegistry), что делает добавление новых команд изолированным и предсказуемым.

Команда Назначение
help Справка по командам (обрабатывается клиентом)
info Тип коллекции, дата инициализации, размер
show Вывести все элементы (отсортированы)
insert <key> Добавить элемент по ключу
update <id> Обновить элемент по id
remove_key <key> Удалить элемент по ключу
clear Очистить коллекцию
execute_script <file> Выполнить команды из файла (поддержка вложенных скриптов)
remove_lower Удалить все элементы меньше заданного
replace_if_lower <key> Заменить значение, если новое меньше
remove_lower_key <key> Удалить элементы с ключом меньше заданного
remove_any_by_type <type> Удалить один элемент с указанным типом
filter_greater_than_type <type> Элементы с типом больше заданного
print_field_ascending_fuel_type Значения поля fuelType по возрастанию
save Сохранить коллекцию (только на сервере)
exit Завершить работу

Надёжность и хранение

  • Идентификаторы и даты создания назначаются на сервере, клиент их не задаёт.
  • Коллекция загружается из CSV при старте; при ошибке чтения сервер стартует с пустой коллекцией и пишет предупреждение в лог.
  • Сохранение выполняется по команде save, при exit и через shutdown hook — данные не теряются при штатном завершении.
  • Все ошибки команд преобразуются в Response.error(...) и возвращаются клиенту, не роняя сервер.

Структура проекта

ITMO_Lab6/
├── README.md
├── data.csv                        # пример файла коллекции
├── report.docx                     # отчёт по лабораторной работе
├── Диаграмма классов/              # UML-диаграммы классов (PlantUML + PNG)
│   ├── class-diagram-common.puml / .png
│   ├── class-diagram-server.puml / .png
│   └── class-diagram-client.puml / .png
└── vehicle-collection/             # многомодульный Maven-проект
    ├── pom.xml                     # родительский POM (агрегатор)
    │
    ├── common/                     # общий модуль (модели + протокол)
    │   └── src/main/java/ru/student/vehicle/common/
    │       ├── model/              # Vehicle, Coordinates, VehicleType, FuelType, VehicleData
    │       ├── protocol/           # Request, Response, CommandType
    │       └── net/                # Serialization
    │
    ├── server/                     # серверный модуль
    │   └── src/main/java/ru/student/vehicle/server/
    │       ├── ServerMain.java     # точка входа
    │       ├── ServerConsole.java  # консоль сервера (save / exit)
    │       ├── net/                # UdpServer, RequestReader, ResponseSender
    │       ├── command/            # CommandRegistry, CommandHandler
    │       ├── collection/         # VehicleCollectionManager, VehicleFactory, VehicleIdGenerator
    │       └── io/                 # CsvVehicleReader, CsvVehicleWriter, CollectionFileResolver
    │
    └── client/                     # клиентский модуль
        └── src/main/java/ru/student/vehicle/client/
            ├── ClientMain.java     # точка входа, REPL-цикл
            ├── net/                # UdpClient
            └── console/            # CommandReader, VehicleDataReader, ClientScriptExecutor

Сборка и запуск

Требования

  • JDK 17+
  • Maven 3.8+

Сборка

cd vehicle-collection
mvn clean package

Запуск сервера

Перед запуском задаётся путь к файлу коллекции через переменную окружения:

export VEHICLE_COLLECTION_FILE=/абсолютный/путь/к/data.csv
java -jar server/target/server-*.jar          # порт по умолчанию 5566
# либо с указанием порта:
java -jar server/target/server-*.jar 5566

Запуск клиента

java -jar client/target/client-*.jar           # localhost:5566 по умолчанию
# либо с указанием хоста и порта:
java -jar client/target/client-*.jar localhost 5566

После запуска клиента введите help для списка команд.


Тестирование

Модульные тесты (JUnit 5) покрывают ключевую логику:

  • VehicleCollectionManagerTest — операции над коллекцией (вставка, обновление, фильтрация, удаление).
  • VehicleDataTest — валидация полей модели.
  • SerializationRoundTripTest — корректность сериализации/десериализации протокола (round-trip).
cd vehicle-collection
mvn test

Выводы по работе

  • Реализована полноценная архитектура «клиент — сервер» с сетевым обменом по UDP; логика хранения и обработки данных полностью вынесена на сервер, клиент отвечает только за ввод-вывод.
  • На практике освоены два подхода к работе с сетью: блокирующий DatagramSocket и неблокирующий DatagramChannel с мультиплексированием через Selector.
  • Решена характерная для UDP проблема — собственный прикладной протокол с сериализацией, повторными попытками и разбиением больших сообщений на чанки обеспечил надёжную доставку.
  • Многомодульная структура Maven показала ценность разделения ответственности: общий код вынесен в common, а клиент и сервер развиваются независимо.
  • Продумано сохранение состояния (по команде, при выходе и через shutdown hook) и устойчивость к ошибкам ввода — сервер не падает при некорректных данных или командах.
  • Бизнес-логика подкреплена модульными тестами, что упростило проверку корректности при изменениях.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages