shared-memory-file-transfer
Shared memory file transfer.
- Quiet · last change 2-19-2019
- ★ 1 on GitHub
README
Писалось и отлаживалось в Delphi 10.1.2 Berlin в 32-х битном режиме под Windows 10 x64.
Задача - переcылка файлов через shared memory определенного размера. Возможность одновременной передачи нескольких файлов. Серверная и клиентская части.
АЛОГРИТМ.
Задача сводится к подзадачам:
- синхронизация доступа к shared memory со стороны одного сервера и множества клиентов
- протокол обмена между сервером и клиентом
- аллокатор памяти внутри shared memory
- синхронизация доступа к shared memory со стороны одного сервера и множества клиентов
Вся синхронизация между разными процессами происходит с помощью именованных мютексов.
Изначально жестко задано имя одного мютекса для "раздачи" имен мютексов клиентам.
Все имена мютексов - это GUID. Из-за простоты генерации в дельфях.
Передающая/принимающая часть клиента и соответственно принимающая/передающая часть сервера образуют двунаправленный поток данных (stream). Таких потоков может быть множество как в одном клиенте (одном процессе), так и в разных процессорах. Так что, к примеру, нет разницы - если мы запустим одного клиента (один exe файл) с 10-ю потоками данных или 10 клиентов (10 exe файлов) по одному потоку в каждом. Для каждого потока данных (stream) создается свой поток операционной системы (thread).
После получения клиентом уникального имени мютекса, сервер обновляет выдаваемое имя (GUID) для другого клиента. "Раздача" GUID'ов может происходить до бесконечности.
Shared memory имеет следующую организацию:
- в начале располагается область для "раздачи" имен мютексов. (в одном экземпляре)
- после нее идут записи, отвечающие за каждый поток данных. выдаваемые мютексы синхронизируют доступ именно к этим записям. в этих записях реализован и протокол обмена клиента с сервером (и наоборот). Занятая область с записями растет от младших адресов к старшим.
- блоки памяти непосредственно для передачи файлов (буфера) - растут в обратном направлении. От старших адресов к младшим.
- протокол обмена между сервером и клиентом
Весь протокол обмена состоит из кода команды и дополнительных числовых и строковых полей.
Одна из передающих сторон захватывает мютекс, анализирует данные, заполняет ответное сообщение (или признак окончания работы) и отпускает мютекс. Команды, обрабатываемые сервером и клиентом не должны пересекаться по коду команды. Иначе сама отправляющая сторона может начать обрабатывать свое же сообщение.
D В данный момент реализованы команды для передачи файла и ping-pong.
- аллокатор памяти внутри shared memory
Как было сказано - аллокатор оперирует двумя типами сущностей - записями и буферами. списки записей и буферов растут навстречу друг другу. При удалении данных, по возможности, новые запросы к аллокатору памяти будут использовать возникающие "дырки" в выделенной памяти.
ПРОБЛЕМЫ И СПОСОБЫ УЛУЧШЕНИЯ
- Аллокатор памяти "деревянный" и написан "в лоб".
- Обслуживание потоков осуществляется как одна задача - один поток. При увеличении потоков увеличиваются накладные расходы на переключение контекстов и т.д. Решается использованием "портов завершения" (Completion Port) операционной системы.
- Обслуживание ввода-вывода (чтение-запись). Решается "портами завершения" или "перекрытым вводом-выводом".
- Синхронизация доступа из разных потоков (и процессов). Вместо мютексов и жестких блокировок можно использовать атомарные операции. И сделать синхронизацию без блокировок (Lock Free).
- Unit тесты покрывают только аллокатор.
КОНФИГУРАЦИОННЫЙ ФАЙЛ и ЗАПУСК СЕРВЕРА И КЛИЕНТОВ
Конфигурационный файл представляет собой xml файл следующей структуры:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <streams> <server outputpath="c:\dst" /> <stream id="1" file="d:\Music\Тяжелое - наше\Чёрный Обелиск\Альбомы\2017 - Акустика\01. Время.mp3" /> <stream id="2" file="d:\Music\Тяжелое - наше\Чёрный Обелиск\Альбомы\2017 - Акустика\02. Свобода.mp3" /> ... </streams>
Файл для сервера и клиентов единый. Имя - options.xml
для сервера: <server outputpath="c:\dst" /> - путь к папке, куда будут сохраняться файлы. По умолчанию - папка с exe файлом сервера
для клиентов: <stream id="1" file="d:\Music\Тяжелое - наше\Чёрный Обелиск\Альбомы\2017 - Акустика\01. Время.mp3" />
id - уникальный числовой идентификатор задачи (потока данных). file - файл для передачи.
Запуск сервера - без параметров - sharedserver.exe
Запуск клиента(ов) - обязательно с параметрами. Если без параметров - он выдаст подсказку. Параметры - номера потоков данных из конфигурационного файла. например: sharedclient.exe 1 2 3 4 5 6 - запустит 6 параллельных потоков данных.
запуск нескольких клиентов: sharedclient.exe 1 2 3 4 5 6 sharedclient.exe 7 8 9 10 11 12 запустятся 12 потоков данных в 2-х процессах. несколько клиентов НЕЛЬЗЯ запускать из одного bat или cmd файла. Точнее - можно, но они выполнятся последовательно. Причем второй - только после завершения первого.
Константин Певцов (rbwsok@gmail.com)

