Web-Development in C++
Deprecated: Function split() is deprecated in /var/kunden/webs/www-0003/pastacode/wp-content/plugins/codeviewer/codeviewer.php on line 75
Deprecated: Function split() is deprecated in /var/kunden/webs/www-0003/pastacode/wp-content/plugins/codeviewer/codeviewer.php on line 75
Deprecated: Function split() is deprecated in /var/kunden/webs/www-0003/pastacode/wp-content/plugins/codeviewer/codeviewer.php on line 75
Deprecated: Function split() is deprecated in /var/kunden/webs/www-0003/pastacode/wp-content/plugins/codeviewer/codeviewer.php on line 75
Php ist inzwischen überall… und hat sich zur Programmiersprache des dynamischen Webs etabliert. Aber was, wenn es zu langsam wird?
Sicher: es gibt den eaccelerator und noch andere Möglichkeiten PHP schneller zu machen. Im großen und ganzen mag ich PHP aber gar nicht so sehr, also begab ich mich auf die Suche nach Alternativen. Warum nicht C++? Es war etwas schwer an die richtigen Informatinen zu kommen und es existieren auch noch alte Informationen die C(++) in Zusammenhang mit dem in die Jahre gekommenen CGI verwenden.
Stand der Dinge: FCGI ist die neue allgemeine Schnittstelle über die man in fast allen möglichen Programmiersprachen Webprojekte programmieren kann. Unterstützt wird das von Apache über mod_fcgi. Für C++ exisitiert inzwischen fastcgipp, eine Library mit einer kleinen Priese Framework, die jedem C++ Entwickler einen einfachen Zugang zur Webentwicklung geben sollte. Die Konfiguration von mod_fcgi soll hier aber nicht weiter erläutert werden.
Nachdem man seinen Webserver eingerichtet hat und fastcgipp kompiliert hat, kann es losgehen. Ein Beispielcode sagt mehr als Tausend Worte… Also hier ein kleines Programm, das ein paar Session Variablen ausgibt und mit q= einen GET-Parameter übergeben bekommt. Das auslesen einer GET-Variable funktioniert in fastcgipp etwas spartanischer als man es von PHP gewöhnt ist, man muss es nämlich per Hand machen. Da Boost sowieso von fastcgipp benötigt wird, kann man aber auch sehr bequem boost.regex (eine C++-Library für reguläre Ausdrücke) für diese Aufgabe verwenden.
#include <fstream>#include <fastcgi++/request.hpp>#include <fastcgi++/manager.hpp>#include <string>#include <fstream>#include <wchar.h>//#include <locale.h>#include <boost/regex.hpp>//#include <vector>//eigenes Error logvoid error_log(const char* msg){using namespace std;using namespace boost;static ofstream error;if(!error.is_open()){error.open("/tmp/errlog", ios_base::out | ios_base::app);error.imbue(locale(error.getloc(), new posix_time::time_facet()));}error << ‘[' << posix_time::second_clock::local_time() << "] " << msg << endl;}//Klasse die von Fastcgipp::Request erbt und bool response() implementiertclass SimpleFcgi: public Fastcgipp::Request<wchar_t>{bool response(){//Header: muss mit zweimaligen \r\n abgeschlossen werdenout << "Content-Type: text/html; charset=utf-8\r\n\r\n"; //charset ist utf8out << "<html><head><meta http-equiv=’Content-Type’ content=’text/html; charset=utf-8′ />";out << "<title>Simple fastcgi++</title></head><body>";//Print Session Parameterout << "<h1>Session Parameters</h1>";out << "<p><b>Hostname:</b> " << session.host << "<br />";out << "<b>User Agent:</b> " << session.userAgent << "<br />";out << "<b>Accepted Content Types:</b> " << session.acceptContentTypes << "<br />";out << "<b>Accepted Languages:</b> " << session.acceptLanguages << "<br />";out << "<b>Accepted Characters Sets:</b> " << session.acceptCharsets << "<br />";out << "<b>Referer:</b> " << session.referer << "<br />";out << "<b>Content Type:</b> " << session.contentType << "<br />";out << "<b>Query String:</b> " << session.queryString << "<br />";out << "<b>Cookies:</b> " << session.cookies << "<br />";out << "<b>Root:</b> " << session.root << "<br />";out << "<b>Script Name:</b> " << session.scriptName << "<br />";out << "<b>Content Length:</b> " << session.contentLength << "<br />";out << "<b>Keep Alive Time:</b> " << session.keepAlive << "<br />";out << "<b>Server Address:</b> " << session.serverAddress << "<br />";out << "<b>Server Port:</b> " << session.serverPort << "<br />";out << "<b>Client Address:</b> " << session.remoteAddress << "<br />";out << "<b>Client Port:</b> " << session.remotePort << "<br />";out << "<b>If Modified Since:</b> " << session.ifModifiedSince << "</p>";//regex um das Argument q aus dem query String zu parsenstd::wstring query_q_matcher= L"(.*)q=([^&]+)(.*)";boost::wregex query_q_exp(query_q_matcher);std::wstring q(session.queryString);boost::wsmatch matches;//wenn der Ausruck matchtif(boost::regex_match(q, matches, query_q_exp)){//gebe ihn ausstd::wstring pattern = std::wstring(matches[2]);out << "<h1>" << "pattern is: " << pattern;}//statt dem eigenen log kann auch das Apache-errorlog verwendet werdenerr << "Hello apache error log";return true;}};int main(){try{Fastcgipp::Manager<SimpleFcgi> fcgi;fcgi.handler();}catch(std::exception& e){error_log(e.what());}}- Download this code: simplefcgi.cpp
Dieser Beispielcode sollte mit
g++ -lfastcgipp -lboost_regex -lboost_thread -O2 -o simple.fcgi simplefcgi.cpp
kompiliert werden können.
Wer möchte, kann es auch direkt hier ausprobieren: http://cgi.pastacode.de/simple.fcgi?lala=schwupp&q=dasistq&u=nochwas
Ich hoffe das der Code einigermaßen selbsterklärend ist. Trotzdem eine kleine Erklärung des Beispiels: Für Fastcgipp benötigt jedes Programm eine Klasse, die Fastcgipp::Request<...> implementiert. Die Funktion bool response() wird bei jedem Request aufgerufen. Im unterschied zu CGI oder PHP, ist die Lauftzeit eines Programms nicht durch einen Request bestimmt, das Programm läuft immer. Es können also auch wichtige Inhalte bei Start der Applikation in den Speicher geladen werden, sodass sie bei jedem Request sofort bereitstehen. Da von der Klasse Fastcgipp::Request
Um sich weiter mit der Materie zu beschäftigen, führt natürlich kein Weg an http://fastcgipp.com/doc/ vorbei.
Pastacode Relaunch…
Mein Komilitone Benni hat nun auch wieder angefangen zu bloggen. Und er legt direkt ziemlich los und schreibt von Web-Development in C++, Openfire unter Linux aufsetzen und Firefox Performance.
Dann wünsche ich Benni doch mal viel Erfolg!
Güße,
Zoki…