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