Skip to content

childhoodisend/astra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Тестовое задание Астра

Формуировка

Клиент хочет получить набор блоков данных переменного размера(1Байт-1Мегабайт) от сервера. Блоки данный идентифицируются по хэшу(например sha1, длина 128 байт). Список хэшей необходимых блоков клиент должен отправить серверу. В ответ сервер должен отправить блоки данных соответствующие запрошенным хэшам клиенту, при этом нужно предусмотреть что размер блоков может быть переменным. Блоки данных на сервере располагаются в блочном устройстве, в случайном порядке. Сервер неким волшебным образом очень быстро может узнать номер блока в блочном устройстве по хэшу с помощью функции - size_t get_block_number(const string& hash). Сервер неким волшебным образом очень быстро может вернуть реальный размер блока в байтах с помощью функции - size_t get_block_size(const string& hash). Сервер неким волшебным образом очень быстро может прочитать данные из блочного устройства с помощью функции - int get_block_data(size_t block_num, char* buffer, size_t buffer_size).

Задача:

Наиболее элегантным образом, с особым вниманием к производительности, реализовать серверную часть протокола взаимодействия клиента и сервера для получения блоков данных клиентом. Также учесть что количество запрашиваемых блоков может быть очень большим.

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

Структура проекта выглядит таким образом:

.
├── CMakeLists.txt - cmake проекта
├── README.md - текущий файл
├── client
│   └── client.py - клиент для подключения к серверу
├── lib
│   ├── CMakeLists.txt - cmake сторонних библиотек
│   └── clsocket - библиотека сокет
└── server
    ├── CMakeLists.txt - cmake серверной части
    ├── block.cpp
    ├── block.h - класс блочного девайса
    ├── main.cpp
    ├── server.cpp
    └── server.h - класс сервера

Серверная часть

Серверная часть работает следующим образом:

  1. Из главного потока создается и запускается экземпляр сервера. При этом считается, что блочный девайс - директория /tmp. Это сделано в качестве заглушки и демонстрации решения.
  2. Сервер запускает поток, слушающий сокет localhost на порте 4000. Ждет подключение клиента.
  3. Если подключение успешно создано, ждет хэш от клиента. Хэш ограничен 40 байтами. Получает номер блока, размер блока, данные блока. Шлет данные клиенту. Буффер данных ограничен 256 байтами. Если новых сообщений не поступает, поток завершает работу. Иначе просто завершает работу с соответствующем выводом в консоль.
  4. Главный поток ждет остановки при помощи ввода симвода q с клавиатуры. После ввода символа, программа завершает работу.

Класс Server

Реализует интерфейс InterfaceServer. Необходим для обеспечения подключения клиента, получения сообщений и отправки данных. Использует два потока - главный и поток обработки подключения.

Класс BlockDevice

Необходим для серверной части. Реализует блочный девайс с функциями:

  1. get_block_number
  2. get_block_size
  3. get_block_data

Использует в качестве единицы хранения путей к файлам std::vector.

Клиентская часть

Реализуется при помощи Python скрипта, использующего библиотеку socket. Работает следующим образом:

  1. Создает сокет "127.0.0.1":4000
  2. Отправлет заранее заданную строку (hash) серверу. Выводит лог отправки сообщения. Ждет ответ.
  3. После получения ответа, выводит его в консоль. Завершает работу.

Используется блокирующий сокет.

Запуск и проверка работоспособности

  1. Сгенерируйте какие-то файлы с названием длины 40 (sha1 hash size) в директории /tmp. Например, "356a192b7913b04c54574d18c28d46e6395428a1" c содержимым "qwerty!\n"

  2. Соберите и запустите сервер

mkdir build
cd build
cmake ..
ninja
cd build/server
./server

Server::Server()
"/tmp/356a192b7913b04c54574d18c28d46e6395428a1" 8
Server::Start() : start
Enter 'q' to quit
Server::start_listen() : start  0x16ef77000
  1. Запустите клиент
cd client
python3 client.py


(base) ➜  client git:(main) ✗ python3 client.py

-----START-----

SEND    356a192b7913b04c54574d18c28d46e6395428a1

RECEIVE qwerty!

Вывод сервера будет примерно таким

Server::receive_msg() m: 356a192b7913b04c54574d18c28d46e6395428a1 b: 40
BlockDevice::get_block_number() 356a192b7913b04c54574d18c28d46e6395428a1
BlockDevice::get_block_size() 0
BlockDevice::get_block_data() 0 8
Server::send_msg() b: 8
Server::receive_msg() : the connection has been shutdown on the other side
Server::start_listen() : stop
  1. Введите символ "q" в консоль, чтобы завершить работу сервера.
q
Server::Stop() : stop
Server::~Server()

Версия компилятора и Python

  1. MacOS silicon
clang 14.0.3 arm64-apple-darwin22.5.0

python 3.11.6
  1. Linux Mint 20.04
gcc 9.4.0 glibc 2.31

python 3.9.12

About

Astra test problem (RuBackup) | 2023

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published