Netzwerkprogrammierung - Erweiterungen
Martin Kompf
Die Weiterentwicklung der in den vorangegangenen Artikeln beschriebenen Client/Server-Anwendung stellt den Programmierer vor eine Reihe von Herausforderungen. Zu deren Bewältigung bedient man sich am besten aus bestehenden Lösungen; stellvertretend für diese wird hier das ADAPTIVE Communication Environment (ACE) vorgestellt.
Bisher wurde in den Artikeln Netzwerkprogrammierung Teil 1 - Client und Teil 2 - Server die Programmierung einer einfachen Client/Server-Anwendung in C beschrieben. Damit läßt sich die Art und Weise des Datenaustauschs über ein Netzwerk mittels eines definierten Protokolls (hier HTTP über TCP/IP) und einer vorhandenen Programmierschnittstelle (im Beispiel die Socket-API) gut demonstrieren. Bis zur Entwicklung einer «richtigen» Applikation ist es allerdings noch ein weiter Weg, verschiedene Anforderungen an eine professionell erstellte Software werden noch nicht erfüllt:
- Portabilität. Die Benutzung der Socket-API ist stark vom verwendeten Betriebssystem abhängig. In den Beispielprogrammen wurde das durch diverse #ifdef _WIN32 Makroanweisungen kaschiert, die bewirken, dass die Programme zumindest unter Windows und Linux laufen. Was aber, wenn sie zum Beispiel auf SGI IRIX oder QNX portiert werden sollen?
- Parallelität. Der Server httpserv ist nur für die gleichzeitige Behandlung eines einzigen Clients ausgelegt. Wenn während einer bestehenden CLient/Server-Verbindung ein weiterer Client einen Verbindungswunsch äußert, so wird er in eine Warteschlange gesteckt (d.h. der Aufruf von connect() auf dem Client blockiert), bis die erste Verbindung beendet wird. Die Warteschlange kann auch nicht beliebig lang werden (im Beispiel kann sie maximal fünf Verbindungswünsche aufnehmen), wenn sie voll ist, werden weitere Clients sofort mit "Connection refused" zurückgewiesen. Dieser Zustand ist natürlich für eine stark frequentierte Website nicht haltbar.
- Implementierung des kompletten HTTP Protokolls. Das Demoprogramm kann derzeit nur den HTTP GET Request bearbeiten und dies auch nur für HTML Dateien. Ein ausgewachsener Webserver sollte mindestens noch den Transfer binärer Dateien, wie Images im GIF- und JPEG-Format, die Verarbeitung von POST und HEAD Requests und die Ausführung von CGI Programmen erlauben.
- Modularisierung und Wiederverwendbarkeit. Die interne Arbeitsweise eines Webservers kann grob in die Bereiche
- physikalisches (TCP-) Connection Management,
- Implementierung des HTTP Protokolls und
- Dateiverarbeitung
untergliedert werden. Diese Bereiche sollten auch programmtechnisch klar voneinander getrennt sein. So lassen sich einerseits Erweiterungen, z.B. von HTTP/1.0 auf HTTP/1.1, leicht vornehmen. Andererseits könnten manche Module auch in anderen Serveranwendungen verwendet werden. Zum Beispiel müssen das physikalische Connection Management und die Dateiverabeitung nicht unbedingt an einen Webserver gebunden sein, sondern sind auch in einem FTP-Server (FTP: File Transfer Protocol) verwendbar. Oder anders ausgedrückt: Um aus einem HTTP-Webserver einen FTP-Server zu machen, bräuchte man dann nur das Modul, welches HTTP implementiert, durch eines ersetzen, welches stattdessen FTP kann und nach außen hin die gleichen Schnittstellen besitzt.
- Konfigurierbarkeit. Die Anforderungen an einen Server sind von Fall zu Fall unterschiedlich. Der eine Anwender möchte möglichst schnell große Dateien per HTTP über das Netz schicken, der andere benötigt vielleicht einen voll ausgebauten Webserver, der auch die Ausführung von Java Server Pages (JSP) und sichere Verbindungen per SSL (Secure Socket Layer) erlaubt. Natürlich wäre es möglich, für jede unterschiedliche Anforderung einen neuen Server zu bauen. Dann wird man bei entsprechend vielen unterschiedlichen Anwendungsszenarien bald nicht mehr vor Arbeit aus den Augen sehen können. Besser ist hier eine Software, die vom Anwender selbst entsprechend seinen Bedürfnissen konfiguriert werden kann. Idealerweise sollte dies auch keine separaten Übersetzungsläufe erfordern, sondern durch dynamisch ladbare Module erfolgen.
- Performance. Wenn im vorliegenden Beispiel eine Datei mehrmals hintereinander von einem Client angefordert wird, dann lädt sie httpserv jedesmal von der Platte in den Arbeitsspeicher. Eine deutliche Performanceverbesserung ließe sich demnach erzielen, wenn eine oft angeforderte Datei im Arbeitsspeicher gecacht werden würde.
Bei genauerer Analyse dieser Anforderungen wird man feststellen, dass sie keinesfalls nur auf den konkreten Anwendungsfall eines Webservers zutreffen. Vielmehr wird man bei fast jeder anspruchsvollen Netzwerkapplikation mit diesen Themen konfrontiert werden. Es zeigt sich, dass die Arbeitsweise fast jeder Anwendung immer den gleichen Mustern (engl. Pattern) folgt. Was liegt also näher als die Idee, zunächst Software zu schreiben, die die Komponenten einer allgemeinen Netzwerkapplikation nach diesen Mustern realisiert! Die konkrete Anwendung - sei es ein Webserver, Fileserver oder Teil eines Datenbankservers - ließe sich dann aus den vorgefertigten Komponenten relativ schnell und einfach «zusammenschrauben».
Zum Glück haben sich schon viele kluge Leute diese Gedanken gemacht und solche Entwurfsmuster für fast alle Bereiche der Softwareentwicklung realisiert. Beispielhaft sei an dieser Stelle das ADAPTIVE Communication Environment (ACE(TM)) erwähnt. Dieses frei verfügbare und als Open Source vorliegende Framework beinhaltet die meisten für einen Netzwerkserver notwendigen Komponenten, die bei der Lösung der oben genannten Anforderungen helfen können:
- Der Operating System Adaption Layer hilft bei der Portierung der Netzwerkapplikation auf die verschiedensten Betriebssysteme.
- C++ Wrapper ermöglichen dem Entwickler den bequemen, abgekapselten Zugriff auf die Betriebssystemressourcen.
- Verschiedene Framework-Komponenten, wie Event Demultiplexing, Service Initialisierung und Konfiguration und Hierarchisch aufgebaute Streams können zur Realisierung der Anforderungen an Konfigurierbarkeit, Parallelität und Wiederverwendbarkeit benutzt werden.
Ein Beispiel, wie die vom ACE gelieferten Komponenten zur Entwicklung eines kompletten, hoch performanten und portablen Webservers verwendet werden können, ist das Projekt des JAWS Adaptive Web Server.
Weitere interessante Artikel
Links zum Thema