Nach langer Zeit gibts mal wieder ein Wallpaper von mir. Wer für das neue Jahr also seinen Desktophintergrund erneuern will, kann hier zuschlagen.

Downloads

In letzter Zeit habe ich wieder etwas mehr Muse zu bloggen und werde auch die nächsten Wochen hier etwas aktiver sein. Besonders rsslounge, das ich die letzten Monate arg vernachlässigt habe, kommt auf die Agenda. Ein neuen Release mit einigen kleinen Verbesserungen wird es also bald geben. Darüber hinaus möchte ich wieder etwas mehr über interessante Dinge aus dem Bereich Softwareentwicklung und Fotografie schreiben.

In diesem Sinne bis zum nächsten Post. Ich hoffe es gibt noch einige interessierte Leser!

Nachdem sich ja schon länger Piraten auf meinem iPad tümmeln (siehe Guybrush Threepwood ist zurück), gabs nun auch das passende Casemodding dazu:

Wer auch eins will (die Sticker gibts auch für iPhone usw.), kann sich hier welche besorgen: jobbyroger.com

Bin ja auch immernoch am überlegen mir diesen Aufkleber zu besorgen. Weiß nur nicht, wo ich den aufkleben soll…

(P.S.: das nächste Mal gibts wieder einen gehaltvolleren Blogeintrag, versprochen ;) )

Bei dem iPhone und iPad und iWasweißichwas-Hype kommt man ja als Webentwickler nicht mehr darum herum auch aufzurüsten und seinen Content auch auf Briefmarkengröße anzubieten. Bei WordPress ist das glücklicherweise sehr einfach. Das Plugin WPtouch erweitert den Blog und stellt auf iPhones ein passendes und optimiertes Theme zur Verfügung. Das habe ich für diesen Blog mal gemacht und bin mit dem Ergebnis ganz zufrieden. Also: wer jetzt mobil auf blog.aditu.de surfen will kann das jetzt problemlos machen ;)

Jetzt ist es schon wieder einige Zeit her, dass ich hier etwas geschrieben habe und ich denke ich gebe mal ein Lebenszeichen von mir. Natürlich gibt es zahlreiche interessante Themen in meiner Queue zum bloggen, aber wie immer findet man nicht die Zeit oder nötige Ruhe dazu.

Die Problemstellung

Nun aber zum Thema: für ein aktuelles Projekt benötige ich, von meiner PHP Webapplikation heraus, den Zugriff auf einige Hardwarekomponenten. Zudem will ich einige Fremdbibliotheken verwenden, die sehr rechenintensive Aufgaben übernehmen und auch nur in C++ zur Verfügung stehen. Die Frage ist also: wie kann ich diese Komponenten an mein PHP Programm ankoppeln?

Für Java gibt es eine ganz gute Server Bridge, die innerhalb der Java Virtual Machine einfach einen kleinen Server startet, der XML Anfragen entgegen nimmt, stellvertretend ausführt und das Ergebnis, auch wieder über eine XML Kommunikationsschnittstelle, zur Verfügung stellt. Die nötige PHP Klasse wird ebenfalls durch den Java Server direkt zur Verfügung gestellt. Eine ähnliche Bridge Lösung bringt auch der Zend Server bereits out of the box mit.

Für C++ habe ich so eine Lösung nicht gefunden und als weiteren Ansatz überlegt, eine PHP Extension zu entwickeln. Sowohl für Linux, als auch für Windows, gibt es hier Tutorials (siehe “Extension-Entwicklung unter WAP“, “Wrapping C++ Classes in a PHP Extension” oder “Extension Writing Part I: Introduction to PHP and Zend“). Allerdings ist, neben den Tutorials, der ganze Vorgang nicht gut dokumentiert und scheinbar muss das Kompilat der Extension exakt dem des verwendeten PHP Kompilats entsprechen. Insgesamt also eher eine wackelige Angelegenheit.

Lösungsansatz

Meine Lösung ist hingegen pragmatisch und verfolgt eine eher losere Kopplung: Meine C++ Komponenten werden in ein eigenständiges Programm ausgelagert, das selbst, über einen gewöhnlichen HTTP Server, die benötigten Dienste zur Verfügung stellt. Dabei orientiere ich mich an dem REST Architektur Prinzip und binde jeweils eine Teil-Funktionalität an eine feste URL. Die Parameter und Rückgabewerte werden mittels JSON kodiert. Von PHP Seite aus, wird der Aufruf der C++ Komponenten sauber gekapselt, so dass für das PHP Programm der Eindruck entsteht, dass eine gewöhnliche Funktion aufgerufen wird.

Welche Vor- und Nachteile hat das Vorgehen? Zum einen ist die in C++ implementierte Funktionalität sauber gekapselt und von der Webapplikation getrennt. Dadurch wird die Software leichter wartbar. Durch eine saubere Schnittstellendefinition, kann die C++ Serverkomponente auch unabhängig vom Wissen über die PHP Applikation gepflegt werden. Zum anderen entsteht aber ein zusätzlicher Aufwand (mit zusätzlichen Fehlerquellen). Die Schnittstelle muss definiert und implementiert werden, ein Fehlerhandling muss durchgeführt werden und eine zusätzliche Serverapplikation muss gestartet werden, was hinsichtlich der Sicherheit berücksichtigt werden muss. Dennoch halte ich die Lösung für die eleganteste, denn sie nutzt genau die Vorteile der Vernetzung und der losen Kopplung aus. So könnte die C++ Komponente bei höherer Last auch leicht auf einen eigenen Server umgezogen oder unabhängig von der Webapplikation betrieben werden.

Implementierung

In der Theorie hört sich natürlich immer alles ganz nett an, aber wie sieht das mit dem HTTP Server aus? Hier gibt es eine hervorragende C++ Bibliothek, mit der sich ohne großen Aufwand eine solcher HTTP Server realisieren lässt. mongoose heißt das Wunderding, steht unter der MIT Lizenz unter Google Code zur Verfügung. Es unterstützt Windows, Linux und Mac OS X, bietet eine CGI Schnittstelle, SSL Verschlüsselung, ACL, eine saubere API und ist nicht größer als 60 kB. Die Dokumentation ist zwar recht knapp, aber dank Beispiele findet man sich schnell zurecht und auch die API Beschreibung ist vollkommen ausreichend.

Will man einen eigenen Server starten, so muss zuerst ein neuer Context erzeugt werden:

struct mg_context* ctx;
ctx = mg_start();

Mit mg_set_options, werden die Servereinstellungen geändert. Folgende zwei Zeilen deaktivieren das Directory Listing und setzten 8080 als Port.

mg_set_option(ctx, "dir_list", "no");
mg_set_option(ctx, "ports", "8080");

Aus Sicherheitsgründen erlaube ich nur einen Zugriff vom selben Rechner aus, also erlaube nur die IP Adresse 127.0.0.1:

mg_set_option(ctx, "acl", "-0.0.0.0,+127.0.0.1");

Mit mg_set_uri_callback kann ein Pointer auf eine eigene Funktion an eine URL gebunden werden. Diese wird aufgerufen, wenn der Client die URL aufruft, wobei die URL auch Wildcards enthalten kann.

mg_set_uri_callback(ctx, 'dosomething', &Server::dosomething, NULL);

Als dritter Parameter darf ein Pointer (void*) auf ein beliebiges Objekt übergeben werden. Die Callback Methode bekommt dazu alle notwendigen Parameter, wie die aktuelle Verbindung, den aktuellen Request und das zuvor übergebene Objekt (hier NULL) übergeben.

void Server::capture(struct mg_connection *conn,
 const struct mg_request_info *request_info,
 void *user_data) {
char* param = mg_get_var(conn, "param");
mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
}

Mit mg_printf kann dann eine Antwort an den Client gesendet werden. Hier als einfaches Beispiel einfach nur ein OK (HTTP 200). In meinem Szenario wird hier der generierte JSON Text zurück gegeben. Mit mg_get_var können übergebene Parameter (POST, GET) ausgelesen werden. Wichtig: um memory leaks zu vermeiden, müssen diese mit mg_free wieder freigegeben werden.

Natürlich ist das nur die eine Hälfte. PHP muss jetzt auch Funktionen, auf dem Server, aufrufen können. Dazu kommt der Zend_Http_Client zum Einsatz. Dieser ist im Zend Framework enthalten, mit etwas Frickelei kann er aber auch aus dem Gesamtpaket heraus gepickt werden. Da ich aber das Zend Framework für die ganze Anwendung nutze, ist das Aufrufen der URL und das Decodieren des JSON Strings in einen Action Helper ausgelagert, der gleichzeitig eine einfache Fehlerbehandlung durchführt:

class JsonHttpHelper extends Zend_Controller_Action_Helper_Abstract {
   public function get($url, $params = array()) {
      try {
         $client = new Zend_Http_Client($url);
         foreach($params as $param=>$value)
            $client->setParameterPost($param, $value);
            $response = $client->request('POST');
            $res = Zend_Json::decode($response->getBody());
            if($response->isSuccessful()) {
               return $res;
            } else {
               return array("error" => "request not successfully: ".$res["error"]);
            }
      } catch(Exception $e) {
         return array("error" => $e->getMessage());
      }
 }
}

Bisher bin ich mit der Lösung sehr zufrieden. Besonders mongoose kann ich nur wärmstens empfehlen. Auch von der Verarbeitungsgeschwindigkeit ist das Ergebnis zufriedenstellend und kann sich sehen lassen. Um den Rahmen nicht zu sprengen, habe ich die serverseitige Generierung und Verarbeitung von JSON außen vor gelassen. Hier gibt es aber auch zahlreiche Bibliotheken, so dass die Suche nicht schwer fallen dürfte.

Nach meinem Blog ist jetzt meine Homepage dran und hat eine Rundumerneuerung bekommen. Sie ist nun auch viel schlichter geworden und soll schnell und unkompliziert einen Überblick über meine Fotografie und meinen Aktivitäten im Netz geben. Feedback ist willkommen und ich bin gespannt ob die Seite gefällt.

Screenshot www.aditu.de

Lange ist es her, dass ich etwas an meinem Blog verändert habe. Nun habe ich mich entschlossen meinen Blog von einem selbst entwickelten System auf WordPress umzustellen. Wenn auch das Backend ordentlich und ausbaufähig war, fehlt mir die Zeit den Blog zu erweitern und mit nützlichen Funktionen anzureichern. Hier macht es einen WordPress und die große Auswahl an Plugins sehr einfach. Ich bin mir auch noch nicht sicher, was ich von dem Backend von WordPress halten soll. Doch die Vorteile überwiegen: gut testeter Code, komfortables Backend, leicht anzupassen, viele Plugins usw.

Natürlich bin ich mir im Design treu geblieben und habe den Grünton, der meine Webauftritte nun schon seit 10 Jahren begleitet übernommen. Es soll auch wieder schön schlicht sein und durch Einfachheit und Übersichtlichkeit bestechen. Natürlich darf auch ein stylischer Twitter Vogel (siehe ganz unten) nicht fehlen ;)

Wenn jemand eine Fehlfunktion findet oder mit etwas Probleme hat, dann bin ich über Feedback sehr dankbar. Gerade wenn man etwas neu einführt hackt es immer mal wieder an Details.