#3 dyvniy » Пн, 28 июля 2014, 09:57:11
Ни лучше ли Apache FastSGI
http://habrahabr.ru/post/61532/- Спойлер
- Apache, fastcgi и c++: «Hello, world»
C++*
img
Писать web-приложения на C/C++ дело неблагодарное. Многие говорят, что это полное безумие, когда есть PHP и Perl. И я с ними согласен. Это очень просто написать сайт на PHP(особенно используя фреймворки вроде Zend Framework).
Но..(всегда есть какое-то «но»).
Давайте не будем забывать, что простота использования складывается не только из простого синтаксиса. Учитывается множество параметров. И одним из весомых параметров является наличие статей «Get started with ...» с примерами «hello, world»-программ. Я собираюсь добавить немного простоты написанию fastcgi на C/C++. И если прочитав эту статью хоть один человек скажет «А это не так уж и сложно», то я буду считать свою миссию выполненной.
Чтобы пройти весь путь от пустого исходника до надписи на экране браузера, нам придется настроить веб-сервер( в нашем случае Apache), установить на него mod_fastcgi, выбрать библиотеку libfcgi и наконец написать «Hello, world»-программу.
Вступление: FastCGI
О том что такое fastcgi можно прочитать здесь. Если говорить коротко, то это CGI-программа обрабатывающая запросы в цикле. Её преимущество над обычной CGI-программой заключается в что она запускается один раз для обработки множества запросов.
Веб-сервер
Для работы подойдет любой веб-сервер поддерживающий fastcgi интерфейс.
Так сложилось, что все мои попытки взаимодействия с веб проводились с использованием веб-сервера Apache. Выбор его для этой статьи обусловлен скорее его наличием и работой на нем других проектов, чем какими-то особенными характеристиками.
Возможные альтернативы:
Nginx и Lighttpd имеют «родную» поддержку интерфейса fastcgi и их использование более предпочтительно на «продакшн»-серверах. Можно также использовать MS IIS.
Mod_fastcgi, mod_fcgid
Мне известно два модуля при помощи которых осуществляется поддержка fastcgi-интерфейса в апаче, это mod_fastcgi и mod_fcgid.
Mod_fastcgi разрабатывается компанией Open Market c 1997года. Последняя версия 2.4.6 была обновлена 13го ноября 2007 и, как уверяют авторы, является очень стабильной.
Mod_fcgi, судя по домену, разрабатывается китайскими программистами. Последняя версия 2.2 датирована 31июля 2007. Отличительными особенностями от mod_fastcgi являются: новая модель управления fastcgi-программами, обнаружение ошибок в работе fastcgi-программ. Модуль имеет бинарную совместимость и поэтому перекомпилировать программы, работающие под mod_fastсgi нет необходимости.
Используя development kit с fastcgi.com для разработки программ, я решил, что более уместно будет использовать mod_fastcgi, т.к. они используют общую библиотеку libfcgi.
Для подключения модуля mod_fastcgi необходимо добавить в httpd.conf:
LoadModule fastcgi_module modules/mod_fastcgi.so
AddHandler fastcgi-script .fcg .fcgi .exe
Типы запуска fastcgi-программ
Используя mod_fastcgi можно запускать программы тремя различными способами: динамически, статически и удаленно.
Динамический способ запуска: В момент начала работы apache создает только process manager(PM), ожидающий входящих запросов. Как только первый запрос получен, process manager создает экземпляр программы для его обработки. В зависимости от настроек, после обработки запроса программа может быть завершена PM’ом, либо может быть использована для обработки последующих запросов. С помощью настроек можно задавать множество параметров создаваемого пула приложений, такие как минимальный и максимальный размер, время жизни приложений, максимальный размер очереди запросов и другие.
Директива: FastCgiConfig option [option ...]
Статический способ запуска: В момент начала работы apache создает PM, который в свою очередь создает заданное количество экземпляров программы для обработки входящих запросов.
Директива: FastCgiServer filename [option ...]
Удаленный способа запуска: Приложение запускается независимо от apache и PM. PM выступает в роли proxy.
Директива: FastCgiExternalServer filename -host hostname:port [option ...]
FastCgiExternalServer filename -socket filename [option ...]
Методы взаимодействия:
Stdin
Unix domain socket / named pipe
TCP Socket
Stdin: Используется при динамическом способе запуска fastcgi-программ. Взаимодействие происходит через Standard in file descriptor.
Unix domain socket / Named pipe: Может быть использован, как при статическом так и при удаленном способе запуска fastcgi-программ. При статическом способе socket создается process manager’ом, при удаленном способе socket должен быть создан fastcgi-программой. Чтобы использовать данный способ необходимо задать параметр –socket имя_сокета.
TCP Socket: Может быть использован также как и Unix domain socket / named pipe, как при статическом так и при удаленном способе запуска fastcgi-программ. Для использования в статическом режиме необходимо задать параметр -port номер_tcp_порта. Для использования в удаленном режиме параметр -host имя_хоста:номер_tcp_порта.
Меня интересует прежде всего работа с tcp socket'ом и удаленным способом запуска fastcgi-программы, потому что это дает совместимость работы с другими веб-серверами, а также предоставляет более простую возможность отладки.
Fastcgi libraries
Не так уж и много существует библиотек помогающих создавать fastcgi-программы на C/C++. Наиболее популярна libfcgi.lib, которая поставляется в составе development kit от fastcgi.com. Библиотека, честно сказать, предоставляет небогатый функционал для работы.
Существует также Fastcgi++ библиотека классов на С++.
Так как это моя первая fastcgi-программа, то я буду использовать старую, проверенную библиотеку libfcgi.lib.
Hello_world.fcgi
Программа использует для коммуникации TCP Socket, открывая порт номер 9000. В браузере выводится строка «Fastcgi: Hello, world».
Используемые функции:
int FCGX_Init(void);
— Инициализация библиотеки FCGX
int FCGX_OpenSocket(const char *path, int backlog);
— Открывает слушающий сокет (Параметры: path – имя сокета, backlog – глубина стека запросов).
int FCGX_InitRequest(FCGX_Request *request, int sock, int flags);
— Инициализируем структуру запроса для использования внутри FCGX_ Accept_r (Параметры: request – указатель на структуру запроса, sock – слушающий сокет используемый совместно с request, flags – флаг запроса (доступные флаги: FCGI_FAIL_ACCEPT_ON_INTR – не вызывать повторно accept при разрыве).
int FCGX_Accept_r(FCGX_Request *request);
— Получает новый запрос на обработку.
Полный текст программы:
#include <string>
#include "fcgi_stdio.h"
#include <stdlib.h>
#pragma comment(lib, "libfcgi.lib")
int main(int argc, char* const argv[] )
{
std::string port=":9000"; //Задаем номер порта TCP
int listenQueueBacklog = 400; //Глубина стека запросов
FCGX_Stream *in, *out, *err;
FCGX_ParamArray envp;
if(FCGX_Init()) exit(1); //Инициализируем библиотеку перед работой.
int listen_socket = FCGX_OpenSocket(port.c_str(), listenQueueBacklog); //Открываем новый слушающий сокет
if(listen_socket < 0) exit(1);
FCGX_Request request;
if(FCGX_InitRequest(&request, listen_socket, 0)) exit(1); //Инициализируем структуру запроса
while(FCGX_Accept_r(&request) == 0)
{
FCGX_FPrintF(request.out, "Content-type: text/html\r\n\r\n<TITLE>fastcgi</TITLE>\n<H1>Fastcgi: Hello world.</H1>\n");
FCGX_Finish_r(&request);//Завершаем запрос
}
return 0;
}
Vhosts.conf
Кусочек файла настройки vhost.conf отвечающий за helloworld.local:
NameVirtualHost 127.0.0.1:80
<VirtualHost 127.0.0.1:80>
ServerAdmin mail@localhost
DocumentRoot «C:/Apache2/cgi-bin»
ServerName «helloworld.local»
<Directory «C:/Apache2/cgi-bin»>
Options Indexes FollowSymLinks MultiViews ExecCGI
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Directory>
<Files hello_world.exe>
SetHandler fastcgi-script
</Files>
FastCgiExternalServer C:/Apache2/cgi-bin/hello_world.exe -host 127.0.0.1:9000
</VirtualHost>
В папке «C:/Apache2/cgi-bin» у меня находится файл .htaccess, направляющий все запросы к helloworld.local на hello_world.exe.