В рамках данного курса:
- Создать свой репозиторий c задачей на https://github.com.
- Получится Ваш первый открытый проект, который можно показывать будущему работодателю, что характеризует Вас, как специалиста.
- ООП-код, использование функциональности
- Стандартной библиотеки,
- Классов,
- Интерфейсов,
- Шаблонов и пр.
- Тесты
- Отладка багов
- Доказательство работоспособности решения
- Подумать, чем отличаются следующие виды описаний и для чего нужны:
- комментарии,
- readme (цель проекта, решаемая задача),
- getting-started (шаги установки/развёртывания, метод и способ использования в своём коде),
- список зависимостей,
- документация
- Документация
- Если скачать программу doxygen.nl и выбрать папку с вашим правильно оформленным кодом, то doxygen автоматически сверстает документацию в формат html/doc/pdf и др.
- Правила оформления комментариев в коде для получения документации
- Пример такой сгенерированной документации на сайте Данный справочник по функциям и методам удобно читать (лишён ненужных подробностей в отличие от кода) и может быть показан пользователям Вашего проекта
При реализации комментариев и интерфейса, представьте, что вы пишите open-source библиотеку для программистов, сделайте, чтобы удобно можно было создавать объекты ваших проектов у себя в коде.
Сервер
- epoll/kqueue
- libevent/libev
- boost.asio
Клиент
- select/poll
Запрещается использование иных сетевых библиотек. Использование библиотек для реализации содержимого, кроме stl и системных вызовов мультиплексирования и примитивов синхронизации ОС, только по согласованию с преподавателем.
Много-поточный сервер с пулом потоков
либо
Много-процессный сервер с фиксированным количеством исполняющих процессов
При запуске сервер принимает параметр – число потоков/процессов. Необходимо сразу же запустить указанное число исполнителей и обеспечить одновременную обработку запросов, превосходящих число исполнителей. В исключительных случаях допустима блокировка входящих соединений.
Сдавать вместе с нагрузочным тестом, демонстрирующим общую работоспособность.
Для отладки удобно применять утилиты
netcad.exe |
---|
где EOF это Ctrl+D для обрыва соединения |
netcat -q 3 yandex.ru 80 < GET.txt |
где в GET.txt сохраняем подготовленный HTTP GET запрос |
или
curl.exe |
---|
curl http://www.apple.com/hotnews/ > /dev/null |
создастся запрос |
GET /hotnews/ HTTP/1.1 |
User-Agent: curl/7.30.0 |
Host: www.apple.com |
Accept: */* |
Необходимо использовать язык программирования C++. При реализации функциональности стараться соблюдать методологию ООП, RAII, идиом языка С++.
Все варианты заданий предполагают параллельную обработку запросов, т.е. при тестировании необходимо продемонстрировать возможность открыть несколько клиентских сессий и показать, что несколько сессий не ждут завершения операции первой из них. Реализация с пулом потоков или набором процессов не должны иметь ограничений по количеству одновременно открытых клиентских сессий (кроме как по количеству дескрипторов открытых файлов).
Особое внимание уделить тестированию. Трудновоспроизводимые "глюки" при работе сервера интерпретируются как ошибки соревнования, и являются основанием для отказа в приёме задания. После обнаружения таких "глюков" преподаватель имеет право потребовать доказательства корректности используемой схемы синхронизации.
Использование явных и неявных холостых циклов для синхронизации потоков не допускается
(в частности, высокая загрузка процессора (по показаниям top или диспетчера задач)
при малой активности соединений интерпретируется как явный или неявный холостой цикл
и является основанием для отказа в приеме задания).
Сервер должен корректно обрабатывать сброс клиентских сессий. В том числе, в случае, когда 2 или более сессий работали с 1м ресурсом, после сброса одной из них, остальные сессии должны корректно продолжить работу.
Отвечает на HTTP-запросы пользователей на имеющиеся в рабочей папке и её подпапках файлы jpeg-картинок и html-страниц.
Запуск ./wwwsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где лежат html, txt и jpeg файлы сервера |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-s/--secsdrop= | <uint> | количество секунд бездействия клиента, после которого соединение с ним сбрасывается |
-u/--useragent= | <uint> | фильтр разных ответов по значению user-agent-ов |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
Необходима самостоятельная реализация анализа (парсера) заголовка HTTP.
Нужно поддерживать операцию GET, HEAD и частично POST.
Вид HTTP запроса:
header |
---|
GET(HEAD|POST) <URI> HTTP/1.0\r\n |
Header1: something\r\n |
... |
HeaderN: something\r\n |
\r\n |
BODY html/text/jpeg |
Заголовоки ответов от сервера:
header | описание |
---|---|
"HTTP/1.0 200 OK" | в случае успеха |
"HTTP/1.0 404 Not Found" | в случае неудачи |
Подробное описание протокола HTTP
Имеется 1 чат-комната, в которую добавляются пользователи при подключении к серверу.
Запуск ./charsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки сервера, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-u/--userlimit= | <uint> | несколько клиентов |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
Показывать имя (адрес) отправителя, дату и время сообщения перед текстом сообщения.
Показывать технические сообщения: «Welcome, user <…>» самому пользователю, остальным в чат-комнате «user <…> append» и «user <…> leaved».
CHAT client (select/poll)
Запуск ./chatcli
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки сервера, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener |
-p/--port= | <uint> | порт, на котором работает listener |
-m/--maxmsglen= | <uint> | аксимальная длина сообщения |
-v/--verbose | <uint> | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) |
-h/--help | распечатать в консоль аргументы, как использовать программу |
У клиента исполнителей (workers) >=2, где 1 поддерживает соединение, 2 взаимодействует с пользователем.
На сервере будут храниться некоторые хэш-таблицы, которые хранят строковые значения по целочисленному ключу.
Пользователи сервера могут присылать следующие команды:
- "addtable" – пользователь создаёт новую хэш-таблицу и ответом получает её номер.
- "remtable " – удалить хэш-таблицу по номеру может только её создатель.
- "gettable " – получить полную копию хэш-таблицы по номеру может только её создатель.
- "setval key= val= table= ttl=" – положить значение в любую хэш-таблицу по её номеру может любой пользователь.
- "getval key= table=" – получить значение из любой хэш-таблицы по её номеру может любой пользователь.
Ответы сервера:
- "ok key=<uint32_t> table="
- "error key=<uint32_t>"
- "error table="
В случае ошибки в ответ пользователю отсылается конкретная ошибка с описанием.
Запуск ./hashsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-m/--maxtblsz= | <uint> | максимальный размер хэш-таблицы (в числе записей) |
-n/--ntables= | <uint> | максимальное количество доступных хэш-таблиц |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
На сервер подключаются клиенты и время от времени отправляют следующие команды:
- "subscribe <items, …>" – клиент хочет получить от иных клиентов, находясь в такой позиции (точка в n-мерном пространстве) следующие ресурсы, в ответ он ждёт адрес иного клиента, который может предоставить такой набор ресурсов, если ресурсы были предоставлены – объявление стирается.
- "publish <items, …>" – клиент хочет предоставить ресурсы иным клиентам, если ресурсы были предоставлены – объявление стирается.
Ответы на команды клиентов "!ok" или "!error ". Ресурсы – это булев массив длины не более nitems и его значение >= 1. В течении числа секунд = расстоянию между позициями клиентов, выбранные клиенты получают одновременно ответ "!ready" и связанный канал на пересылку сообщений друг-другу, при разрыве успевшие отослаться байты доотсылаются, и клиенты оповещаются "!stop" о конце соединения. Сервер ведёт учёт длительностей всех каналов и заинтересован в минимизации этих длительностей
В случае ошибки в ответ пользователю отсылается конкретная ошибка с описанием.
Запуск ./pubsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-m/--dims= | <uint> | размерность пространства позиции |
-n/--nitems= | <uint> | максимальное количество элементов для сопоставления ресурсов |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
Сервер в начале работы случайно генерирует карту из булевых значений:
- «1» – можно пройти там, где они соседствуют,
- «0» – где пройти нельзя.
Клиенты, подключённые к серверу, перемещаются в многомерном пространстве и отправляют ему сообщения:
- "Am <own_position> want-to " – свои координаты в многомерном пространстве и куда хочет попасть;
Ответы: "!Ok <own_position >" или "!Error <err_text>".
Сервер находит ближайшую точку «1» на карте к желаемой, согласно допустимого размера шага клиента, строит маршрут и отвечает на следующие периодические (с определённой частотой, зависит от клиента) запросы от клиента:
- "Where?" – получить своё следующее положение.
Когда клиент пришёл сервер отсылает "!Done ".
Клиент снова отсылает команду с местом, куда он хочет попасть.
Запуск ./mapsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-n/--ndim= | <uint> | ширина и длина карты |
-s/--step= | <uint> | величина шага клиента (число клеток) |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
В памяти сервера будут храниться скачанные файлы пользователями. Пользователи сервера могут подавать команды:
- "connect to ip:port" – proxy создаёт 2 соединения, 1 – с клиентом, 2 – с требуемым сервером по присланному адресу вида "0.0.0.0:80" (для простоты отладки можно подключаться браузером через свой proxy и слать http-запросы на сайты, от сервера будут скачиваться html-страницы, но тогда надо парсить не такой простой запрос, а подзаголовок Host в HTTP заголовке запроса клиента и разыменовывать домен в IP адрес)
- "disconnect" – proxy обрывает соединение с сервером клиента и ждёт от него иных команд.
- "get list of cached files" – proxy отсылает клиенту список путей до имеющихся у него файлов.
- "get file " – proxy отсылает клиенту сохранённый у себя нужный файл.
- "reconnect to ip:port" – proxy обрывает соединение c текущим сервером и создаёт новое до нужного.
После установлений соединений proxy пересылает запросы клиента серверу и записывает к себе в память (или в файлы) запросы клиента и ответы сервера (не превышая максимального заданного объёма maxdata) и, если запрос клиента повторяется, то отсылает ответ от себя, а не от сервера. Если ответы не помещаются, вытесняет самый старый из них новым. Чтение и запись буферизированы. Корректно обрабатывать закрытия соединений и ошибки. В случае ошибки в ответ пользователю отсылается конкретная ошибка с описанием.
Запуск ./proxysrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-m/--maxdata= | <uint> | объём данных, которые может хранить сервер на 1 клиента |
-v/--verbose | <uint> | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) |
-h/--help | распечатать в консоль аргументы, как использовать программу |
При сбросе единственной сессии, работавшей с записью кэша, допускается как сброс докачки страницы и уничтожение записи в кэше, так и фоновое продолжение докачки.
Сервер будет архивировать поток, получаемый от клиента и будет храниться некоторые файлы.
- "zip <bytes_size>" - далее клиент шлёт байтовый поток, сервер его архивирует и сохраняет файл у себя.
- "get " – клиент требует заархивированный файл с именем,
- "zip-and-get <bytes_size>" – сервер одновременно принимает, архивирует и отсылает сжатые данные обратно клиенту.
- "unzip <byte_size>" - далее клиент шлёт байтовый поток, сервер его архивирует и сохраняет файл у себя.
- "unzip-and-get <bytes_size>" – сервер одновременно принимает, разархивирует и отсылает сжатые данные обратно клиенту.
Ответы
- "OK < name >"
- "Ready "
- "Error <err_text>"
В случае ошибки в ответ пользователю отсылается конкретная ошибка с описанием.
Запуск ./archsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-n/--maxnfiles= | <uint> | максимальная число файлов, что клиент может сохранить |
-r/--reqspermin= | <uint> | максимальная количество обращений на архивацию от 1 клиента в 1 минуту |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
Для полученной от клиента функции y=f(x) построить её график на указанном отрезке [a,b]. Сохранить полученный график в bmp-файл и вернуть пользователю. Уметь отрисовывать графики функций, заданных полиномами f(x) = c + с1 x + с1 x2 + .. сn xn c вещественными коэффициентами (возможно, с использованием модуля |x|) на плоскости.
Клиент может присылать следующие команды:
- "paint <name.bmp> H= W= [, < float>]" – создать файл c полотном размера HxW пикселей с именем name для функции и отрезка, сохранить файл и отправить клиенту.
- "get <name.bmp>" – получить созданный ранее файл по имени.
- "rem <name.bmp>" – удалить созданный ранее файл с именем.
- "list" – получить список имён имеющихся файлов, доступных для данного клиента.
Ответы:
- "Ok "
- "Ready "
- "Error "
В случае ошибки в ответ пользователю отсылается конкретная ошибка с описанием.
Запуск ./graphsrv
аргумент | значение | описание |
---|---|---|
-d/--dir= | <path> | путь до папки, где сохранять файлы |
-i/--ip= | <IP> | IP адрес, на котором работает listener сервера |
-p/--port= | <uint> | порт, на котором работает listener сервера |
-w/--workers= | <uint> | число потоков/процессов одновременных сессий пользователей |
-m/--maxdegree= | <uint> | максимальная степень полинома, которую можно обработать |
-n/--maxnfiles= | <uint> | максимальная число файлов, что клиент может сохранить |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
BMP-файл создаётся следующим образом, в файл записывается побайтово структура заголовка, за ней побайтово построчно записывается регион растровых данных – значений пикселей. Формат заголовка BMP-файла
Простой рекурсивный http-загрузчик содержимого web-страниц.
Запуск ./wget
аргумент | значение | описание |
---|---|---|
-u/--url= | <str> | http-адрес, по которому нужно качать web-страницы |
-d/--dir= | <path> | путь до папки, где сохранять html-страницы |
-r/--recursive | качать страницы по найденным ссылкам на загруженной странице | |
-l/--level= | <uint> | глубина рекурсивного скачивания сайта по ссылкам на страницах |
-t/--tries= | <uint> | число попыток скачать страницу до выдачи ошибки |
-w/--workers= | <uint> | число потоков выкачки |
-n/--no-parent | загружать страницы не выше по иерархии заданной | |
-i/--infile | <path> | путь к входному txt файлу со списком http-ссылок |
-v/--verbose | печатать в stdout подробно производимые операции (без этого флага печатать только ошибки) | |
-h/--help | распечатать в консоль аргументы, как использовать программу |
Проверять status codes = 200, 404, 500, 301.
netcat -q 3 yandex.ru 80 < GET.txt