Введение (лирика)
Около двух лет я занимался веб-разработкой, создавая сайты и веб-приложения на языке PHP. Вот только в веб-разработку я попал по стечению весьма странных жизненных обстоятельств. Не сказать, что мне было это не интересно — мне, как раз, было очень интересно узнать, как создаются сайты и как вообще работает интернет.
Но, в то же время, меня всегда привлекало низкоуровневое программирование. Ещё во время учёбы мне очень понравился язык программирования C++. Только негде было его применять, кроме как для своего развлечения. Дальше я опустился пониже — изучил Assembler. Понял, как работает процессор (хотя слишком поверхностно) и как выполняются программы на самом деле.
Со всем этим набором знаний и опыта я попал в веб-разработку. Всё поначалу казалось весьма и весьма хорошо, оказалось гораздо проще, чем я думал. А со временем приелось, стало слишком просто, неинтересно, нет простора для оптимизаций и интересных решений. Генерируешь веб-странички, пишешь и подключаешь js-скрипты, оформляешь страницы с помощью css. Чувствовал, что больше не развиваюсь как программист.
В то время меня стали мучить вопросы:
- Почему я не могу создавать высокопроизводительные веб-приложения на таком языке, как C++ (не CGI)? Ведь этот язык мне нравится больше всех других. Никогда не слышал о том, что бывают сайты, написанные на C++. Почему?
- Почему веб-разработку захватили скриптовые (интерпретируемые) языки программирования?
С интерпретируемыми языками, конечно, всё понятно. Они очень удобны — не нужно пересобирать весь проект после внесения изменений. При этом все изменения применяются налету, без перезагрузки (остановки) веб-приложения.
Искал ответ на первый вопрос — как писать сайты на C++. В интернете ничего толкового по этой теме не нашёл (только через CGI). И ужаснулся: как же так? Я хочу быть свободен в выборе инструмента разработки, хочу использовать тот язык, который мне нравится. И до сих пор никто ничего не сделал? Или сделал, но использует только у себя?
Это меня и заставило начать разрабатывать свой веб-сервер, где веб-приложения (сайты) подключались бы как библиотеки (*.so, *.dll).
(Во время разработки я прозрел и понял, как правильно использовать HTTP протокол — узнал, что такое RESTful. Узнал, как правильно строить архитектуру веб-приложений. Удивился, какое множество сайтов не соответствуют требованиям RESTful, то есть, фактически, — работают неправильно).
Суть
За год работы над собственным веб-сервером (который я пишу на C++ самых модных новых стандартов) мне удалось реализовать все базовые необходимые функции:
- Отправка файлов (с помощью установки заголовка X-Sendfile);
- отправка сгенерированных приложением HTML страниц;
- понимание и обработка частичных GET запросов;
- получение данных из форм (файлов и текста) в различных видах (application/x-www-form-urlencoded, multipart/form-data) и передача их приложению в готовом виде;
- поддержка Keep-Alive соединений;
- поддержка Upgrade соединений (WebSocket).
Поддержка операционных систем: Linux, Windows
Как работает мой веб-сервер
Веб-сервер при старте подключает к себе библиотеки, указанные в конфигурационных файлах. Пример:
server {
listen 2280;
server_name servertest www.servertest;
server_module /media/projects/sites/servertest/module/servertest_release.so;
server_module_update /media/projects/httpserverapp/httpserverapp/bin/Release/libhttpserverapp.so;
root_dir /media/projects/sites/servertest/www/;
request_max_size 10485760;
}
Где,
- listen — порт для приёма запросов к приложению;
- server_name — имена веб-приложения (сайта);
- server_module — путь к библиотеке, реализующей функционал веб-приложения;
- server_module_update — путь к библиотеке веб-приложения новой версии, используется для обновления веб-приложения без перезапуска самого веб-сервера (почти на лету);
- root_dir — корневая директория файлов сайта (веб-приложения);
- request_max_size — максимальный размер данных запроса (в байтах), если размер данных в запросе больше — запрос игнорируется.
При подключении библиотеки с веб-приложением происходит поиск функций в ней:
- application_call — функция, которая вызывается для обработки каждого запроса;
- application_clear — функция вызывается для освобождения памяти, выделенной под заголовки, которые приходят от веб-приложения к веб-серверу;
- application_init — функция выполняется при успешной загрузке библиотеки, [не обязательна];
- application_final — выполняется при завершении работы веб-сервера, [не обязательна];
Из описания видно, что application_call — главная функция веб-приложения, точка входа. В неё передаются все заголовки (разобранные по отдельности), данные запроса (URI — идентификатор ресурса (строка запроса), параметры запроса "?var1=sample&var2=1000" в разобранном виде), ссылки на файлы (если переданы), данные веб-приложения (корневая директория). Каждый запрос обрабатывается и выполняется в отдельном потоке (thread).
Особенность в том, что так же передаётся и сокет клиента, с которым можно (нужно) работать напрямую.
Основная работа по разработке веб-сервера, можно сказать, завершена. Уже теперь разработчик может создавать свои веб-приложения на любом языке программирования, компиляторы которых позволяют собирать проект в виде библиотеки. Например, языки C и C++.
Конечно, вам понадобится свой собственный сервер (компьютер), чтобы запустить на нём такой веб-сервер (программу) и насладиться скоростью работы веб-приложений. Помните только о том, что использование базы данных резко снижает производительность любых приложений. Но не столько, чтобы совсем отказываться от использования компилируемых языков.
Хотите попробовать?
Исходный код веб-сервера и пример приложения к нему прилагается (используемая IDE — Monodevelop).
Веб-сервер распространяется под лицензией AGPL.
Что дальше?
Веб-сервер в рабочем состоянии, но работать ещё есть над чем (привести код некоторых функций в порядок, написать комментарии к коду).
Далее хотелось бы подробнее разобрать и описать структуру веб-приложения, описать с чего начинать разработку, для тех, кому это может быть интересно.
Сейчас пишу фреймворк для удобной разработки веб-приложений на C++ для моего веб-сервера (пока нет в доступе). На самом же фреймворке разрабатываю сайт для одной компании. Обычный сайт — ничего примечательного, но зато с оптимизациями. Использую СУБД MariaDB.
Автор: