Cassini - Web Server á la .NET

Veröffentlicht: 11. Sep 2002 | Aktualisiert: 22. Jun 2004

Von Christian Weyer

Die Web-Entwicklungsplattform ASP.NET lebt nicht durch die Internet Information Services (IIS) allein. ASP.NET ist vielmehr unabhängig von den IIS. Es gilt nur zu wissen, wie und wo man sich die ASP.NET-Funktionalität zu eigen machen kann. Das beste Beispiel gibt Microsoft selbst: Cassini, der Mini Webserver für ASP.NET.

Auf dieser Seite

 Generische und erweiterbare Architektur von ASP.NET
 Arbeiten mit Cassini
 Cassini im Überblick
 Cassini erweitern
 Cassinische Trennung

Cassini ist ein kleiner Webserver, der in C# geschrieben ist. Er ist frei verfügbar und kommt direkt von Microsoft selbst! Und zu alle dem ist er auch noch sein kompletter Quelltext verfügbar.

Laden Sie sich den Webserver von folgender URL herunter: https://www.asp.net/Projects/Cassini/Download/.

Ursprünglich war Cassini als Mini Webserver für das Projekt ASP.NET Web Matrix (https://www.asp.net/webmatrix/) gedacht. Innerhalb von Web Matrix heißt er dann auch ASP.NET Web Matrix Webserver. Die Implementierungen von Web Matrix und der offenen Cassini-Version unterscheiden sich nur wenig. Der Kern der Programmierung ist der gleiche.

Wenn man Cassini kompiliert, erhält man einen kleinen, feinen aber auch stark eingeschränkten Webserver mit vollem ASP.NET-Funktionsumfang mit ca. 75 KB Größe. All das ist möglich durch eine rein verwaltete Implementierung. Die Funktionalität von Cassini bedient sich also ausschließlich der Klassen und Methoden aus dem .NET Framework. Werfen wir einen Blick auf die Architektur von ASP.NET, um die Arbeitsweise auch von Cassini besser verstehen zu können.

Generische und erweiterbare Architektur von ASP.NET

Die ASP-Programmierer (Active Server Pages) unter den Lesern werden dieses Gefühl kennen: Da steht einem eine relativ mächtige und produktive Entwicklungsplattform für Web-Anwendungen zur Verfügung., nur ist die Webanwendung an einen Webserver gebunden. Neidisch blickt man auf die PHP-, Python- oder gar Java-Entwickler, die sich den Webserver aussuchen können. Bei ASP ließ sich kein einfacher Ausweg aus dieser Situation finden.

Beim Entwurf und der Entwicklung von ASP.NET haben sich Microsoft-Verantwortliche gehörig Gedanken bezüglich dieses Schwachpunktes gemacht. Die Architektur von ASP.NET ist von Grund auf völlig verschieden zum klassischen ASP. Sie ist generisch gehalten, indem man theoretisch und auch praktisch mit relativ wenig Aufwand neue Webserver ASP.NET-fähig machen kann. Zudem ist sie erweiterbar, indem man sehr schnell und einfach neue Funktionalität für ASP.NET-Anwendungen in die Architektur einbinden kann.

Werfen Sie bitte einen Blick auf Abbildung 1. Dort können Sie sehen, wie die IIS mit ASP.NET zusammen arbeiten. Die IIS als Webserver dienen jetzt gewissermaßen nur noch als Web Container, der die Anfragen an ASP.NET-Ressourcen (z.B. ASP.NET Web Forms oder ASP.NET XML Web Services) an die dafür zuständige Instanz weiterleitet.

Diese Instanz ist ein eigener Windows-Prozess mit dem Namen aspnet_wp.exe (WP steht hierbei für Worker Process, sprich Arbeitsprozess). Die bei den IIS eingehenden Anfragen für .aspx oder .asmx werden über die in den IIS registrierte ISAPI-DLL (Internet Server Application Programming Interface) aspnet_isapi.dll mittels Windows Named Pipes (Mittel zur Interprozesskommunikation unter Windows) an den externen Prozess weiter geleitet.

Die IIS haben somit also lediglich die Aufgabe eines Web Dispatchers. Im externen Arbeitsprozess, der ein Win32-Prozess ist, wird über eine COM-Schnitsttelle die Common Language Runtime (CLR) gehostet. Die eigentliche Abarbeitung der ASP.NET-Anfragen findet ausschließlich über verwalteten (managed) Code statt.

Diese Architektur gilt allerdings nur für die IIS in Verbindung mit ASP.NET Version 1.0, die von Microsoft zur Verfügung gestellt wird. Der wichtige Prozess ist der externe Arbeiterprozess, der die verwaltete Implementierung von ASP.NET nutzt (er implementiert das sog. ASP.NET Hosting).

Bild01

Abbildung 1: Architektur von ASP.NET in Zusammenarbeit mit den IIS

Die Tatsache, dass die komplette Logik zum Betrieb von ASP.NET-Anwendungen in der Framework Class Library (FCL) des .NET Frameworks schlummert, macht es einfach, die IIS als Webserver für ASP.NET zu ersetzen. Und genau dieser Tatsache bedient sich Cassini. Die wichtigen Namensräume innerhalb des .NET Frameworks sind hier übrigens System.Web und System.Web.Hosting.

Im Folgenden werde ich Ihnen kurz die Erstellung und Nutzung des Webservers erläutern.

 

Arbeiten mit Cassini

Der Download von Cassini beeinhaltet alle Quelltextdateien und noch einige Hilfedateien. Wenn man die Datei build.bat in einer Kommandozeile mit gesetzten Umgebungsvariablen für die .NET Tools GACUTIL.EXE und CSC.EXE ausgeführt hat, erhält man zwei kompilierte Dateien.

Die Datei Cassini.dll ist das eigentliche Herzstück und trägt die Funktionalität eines Webservers zur Entgegennahme einer Netzwerkanfrage und den Code zum Hosten von ASP.NET. Es ist wichtig, dass sich diese Assembly im Global Assembly Cache (GAC) befindet.

Die Datei CassiniWebServer.exe dient zum Starten der Rahmenanwendung, die dann die Assembly Cassini.dll verwendet. Startet man CassiniWebServer.exe aus dem Windows Explorer heraus, ergibt sich ein Dialog wie in Abbildung 2. Sie können festlegen wo und wie der Webserver arbeiten soll.

Bild02

Abbildung 2: Konfiguration con Cassini über die grafische Oberfläche

Den gleichen Effekt kann man aber auch über die Kommandozeile erreichen. Hier gibt man der Anwendung einfach die Werte als Parameter mit:

CassiniWebServer.exe c:\Temp\MSDN\Cassini\ 1974 /CassiniArtikel

Sind die eingegeben Werte korrekt - d.h. existiert das angegebene physikalische Verzeichnis und ist der Port, auf dem der Webserver Anfragen entgegen nehmen soll, noch nicht von einer anderen Anwendung in Gebrauch - dann bietet Ihnen die Oberfläche mit dem Klicken auf Start den Link zum Webserver an. Ein Klick auf diesen Link öffnet den Standard-Web-Browser mit der gezeigten Adresse. Standardmäßig bietet Cassini hier die Übersicht der im Verzeichnis verfügbaren Dateien an.

Von nun an läuft der Webserver auf dem angegebenen Port. Um nun eine ASP.NET-Anwendung im Cassini ablaufen zu lassen, habe ich eine einfache Web Service-Datei im Verzeichnis abgelegt. Das Ergebnis des Aufrufs https://localhost:1974/CassiniArtikel/default.asmx sehen Sie in Abbildung 3.

Bild03

Abbildung 3: Ein ASP.NET XML Web Service über Cassini aufgerufen und ausgeführt

Nach dieser kompakten Einführung in die Nutzung von Cassini schauen wir uns nun den Mini Webserver etwas genauer an.

 

Cassini im Überblick

Viele werden nun anfangen, sich die tollsten Szenarien in Verbindung mit dem Einsatz von Cassini auszudenken. Doch nicht so schnell! Cassini ist kein vollwertiger Webserver wie die IIS. Cassini ist nicht für den Produktiveinsatz gedacht. Und Cassini hat nicht die Möglichkeiten wie die IIS, Sicherheit und Skalierbarkeit für ASP.NET-Web-Anwendungen zu bieten.

Einsatzgebiete
Cassini ist primär als technologische Studie gedacht, mit der gezeigt werden soll, wie einfach und schnell ein Entwickler einen eigenen Webserver mit ASP.NET-Funktionalität programmieren kann.

Somit ist also vor allem die Vorgehensweise zum Hosten von ASP.NET in eigenen Anwendungen eine Zielsetzung von Cassini. Cassini kann weiterhin dafür verwendet werden, um Webserver und/oder ASP.NET in Ihre eigenen Programme und Produkte einzubauen.

Und nicht zuletzt kann man sich am Quelltext einiges abschauen wenn man andere Webserver fit für ASP.NET machen möchte. So träumen ja schon seit längerem viele der anfangs erwähnten Systemadministratoren von einem Apache ASP.NET.

Aufbau
Cassini besteht aus neun Quelltextdateien. Die tatsächlich wichtigen Klassen und Funktionen befinden sich in den vier Dateien Connection.cs, Host.cs, Request.cs und Server.cs. Hierin ist die Logik für die Netzwerkkommunikation über Sockets und das Hosting von ASP.NET in einem managed Prozess implementiert.

Tabelle 1 zeigt die Dateien in der Übersicht mit einer kurzen Erklärung ihrer Funktionalität. Alle anderen Dateien umfassen Hilfsklassen und Funktionen, beispielsweise zur Manipulation von Byte Arrays und Strings. Mehr will und kann ich an dieser Stelle nicht auf die genaue Implementierung und die Innereien des Hostings von ASP.NET eingehen. Das sollte Gegenstand eines eigenen Artikels sein.

Quelltextdatei

Funktionsumfang

Server.cs

Mantelklasse zur Definition eines Webservers mit Funktionalität zum Starten und zum Stoppen. Leitet die Arbeit an die Klasse Host (in Host.cs) weiter.

Host.cs

Verwaltet die Socket-Verbindungen und leitet eingehende Anfragen an die Klasse Connection (in Connection.cs) weiter.

Connection.cs

Abstrakte Darstellung einer Anfrage. Leitet die Arbeit an die Klasse Request (in Request.cs) weiter.

Request.cs

Verarbeitet die HTTP-Anfragen in Zusammenarbeit mit der .NET-Klasse HttpRuntime und ist von der Basisklasse SimpleWorkerRequest aus dem .NET Framework abgeleitet.

Tabelle 1: Wichtige Dateien und deren Funktionalität

Einschränkungen
Der Mini Webserver Cassini unterliegt einigen schwer wiegenden Einschränkungen. Lassen Sie uns einen Blick auf diese werfen.

  • Cassini erlaubt nur eine einzige Web-Anwendung pro Port. Dies heißt, dass auf Port 1974 in unserem oben stehenden Beispiel nur diese eine Anwendung CassiniArtikel laufen kann. Bei der Implementierung für den IIS ist dies ja glücklicherweise nicht der Fall.

  • Die Standardausführung des Quelltexts von Cassini unterstützt keine sicheren Verbindungen über SSL.

  • Ebenso ist keine Funktionalität für Authentifizierung (z.B. NTLM oder Digest) eingebaut.

  • Der aber wahrscheinlich gravierendste Nachteil ist die Beschränkung von Anfragen auf lokale HTTP-Abfragen. Somit werden alle Fragen, die nicht von localhost stammen nicht bearbeitet.

 

Cassini erweitern

Doch diese Einschränkungen sind nicht weiter schlimm. Denn mit dem Vorliegen des Quelltextes animiert Microsoft ja die Entwicklergemeinde, neue und bessere Funktionalität in Cassini einzubauen.

Somit lässt sich die localhost-Sperre in der Datei Request.cs recht einfach aufheben. Kommentieren Sie folgende Zeilen in der erwähnten Datei einfach aus und erstellen Sie Cassini neu -voilà!:

// Limit to local requests only
if (!_conn.IsLocal) {
   _conn.WriteErrorAndClose(403);
    return;
}

Ebenso kann ich mir noch eine Version von Cassini als Windows-Dienst vorstellen. Abbildung 5 zeigt eine solche Version, die auf meinem PC derzeit als Test läuft. Mit dem .NET Framework und Visual Studio .NET wird die Windows-Dienst-Programmierung übrigens zum Kinderspiel.

So könnte ich diese Liste mit möglichen Erweiterungen und neuen Features noch beliebig fortsetzen - der Fantasie und schöpferischen Kraft des Cassini-Programmieres sind nun wirklich keine Grenzen gesetzt …

Bild04

Abbildung: Cassini läuft als Windows-Dienst

 

Cassinische Trennung

Der Name Cassini steht eng im Zusammenhang mit dem Codenamen von ASP.NET Web Matrix: Saturn. Man spricht nämlich beim Planeten Saturn von der Cassinischen Teilung seiner Ringe.

Aus dem Quelltext von Cassini kann man viel lernen. Trotzdem sollte man sich seiner Einschränkungen bewusst sein. Aus diesem Grund sollte dieser nette Mini Webserver wirklich nicht in einer Produktivumgebung zum Einsatz kommen.

Ich kann mir aber Kernteile des Codes in einer Peer-To-Peer-Anwendung auf Basis von ASP.NET XML Web Services vorstellen, bei der nicht ein großer und komplexer Webserver auf allen beteiligten PCs installiert sein muss. Wie gesagt: der Fantasie sind keine Grenzen gesetzt.