18
Damit Ihre Anwendungen mit anderen Anwendungen über ein Netzwerk wie dem Internet kommunizieren können, stehen Ihnen verschiedene Methoden zur Verfügung. Das vorliegende Kapitel bietet eine Einführung in die Konzepte, die diesen Programmiertechniken zugrunde liegen. In den nachfolgenden Kapiteln werden einige dieser Konzepte etwas genauer betrachtet.
Noch bevor das Betriebssystem Windows überhaupt existierte, gab es bereits das Internet. Es wuchs immer mehr und wurde zum größten TCP/IP-Netzwerk der Welt. Die frühen Sites waren Unix-Rechner, und eine Sammlung von Konventionen û die sogenannten Berkeley-Sockets û wurden die Norm für die TCP/IP-Kommunikation zwischen Unix-Rechnern im Internet. Andere Betriebssysteme implementierten ebenfalls TCP/IP, was beträchtlich zum Wachstum des Internet beitrug. Auf diesen Betriebssystemen begann das Durcheinander, da eine große Bandbreite proprietärer TCP/IP-Implementierungen entstand, bis eine Gruppe von über 20 Herstellern sich für die Erstellung der Winsock-Spezifikation zusammenschloß.
Die Winsock-Spezifikation definiert die Schnittstelle einer DLL, die typischerweise WINSOCK.DLL oder WSOCK32.DLL genannt wird. Die Hersteller schreiben den Code für die Funktionen selbst. In Anwendungen lassen sich diese Funktionen aufrufen, wobei man sichergehen kann, daß der Name, die Bedeutung der Parameter und das letztendliche Verhalten der Funktion immer gleich sind û und zwar unabhängig davon, welche DLL auf Ihrem System installiert ist. So werden unter Windows 95 und Windows NT beispielsweise unterschiedliche DLLs bereitgestellt. Und dennoch kann eine 32-Bit-Winsock-Anwendung unverändert sowohl unter Windows 95 als auch unter Windows NT ausgeführt werden, denn in der Anwendung werden die Winsock-Funktionen in der entsprechenden DLL aufgerufen.
Ein wichtiges Konzept bei der Sockets-Programmierung ist der Port eines Socket. Jede Site im Internet besitzt eine numerische Adresse, die sogenannte IP-Adresse, die typischerweise in Form von vier, durch Punkte getrennten, Zahlen geschrieben wird, z.B. 198.53.145.3. Programme, die auf dem betreffenden Rechner ausgeführt werden, können mit Hilfe von Sockets mit anderen Rechnern Daten austauschen. Wenn nun bei 198.53.145.3 eine Anfrage eintrifft, von welchem Programm sollte diese dann bearbeitet werden?
Anfragen kommen bei dem Rechner mit einer Port-Nummer an, die das Programm bezeichnet, an das die Anfrage gerichtet ist. Einige Port-Nummern sind für Standarddienste reserviert, Port 80 etwa wird von Web-Servern traditionellerweise für die Reaktion auf Dokumentanfragen verwendet, die von Client-Programmen wie dem Netscape Navigator kommen.
Der größte Teil der für die Socket-Programmierung anfallenden Arbeit ist verbindungsbezogen: Die beiden Programme bilden eine Verbindung mit je einem Socket an jedem Ende und senden und empfangen dann Daten entlang dieser Verbindung. Einige Anwendungen ziehen es vor, Daten ohne Verbindung zu senden, doch besteht in diesem Fall keine Garantie, daß die Daten ankommen. Das klassische Beispiel ist ein Zeit-Server, der in regelmäßigen Abständen an alle Rechner in seiner Umgebung die aktuelle Uhrzeit sendet, ohne auf eine Anfrage für diese Information zu warten. Die Verzögerung, die durch den Aufbau einer Verbindung entstünde, würde möglicherweise ein Senden veralteter Daten (der falschen Uhrzeit) zur Folge haben û in diesem Fall ist also ein verbindungsunabhängiger Ansatz vorzuziehen.
Zunächst bedeutete die Sockets-Programmierung in Visual C++ eine Implementierung von API-Aufrufen in die Winsock-DLL. Viele Entwickler erstellen Socket-Klassen, um diese Aufrufe zu kapseln. Visual C++ 2.1 stellte zwei neue Klassen vor: CAsyncSocket und CSokket, die von CAsyncSocket abgeleitet ist. Diese Klassen übernehmen die Verarbeitung der API-Aufrufe, einschließlich der Start- und Bereinigungsaufrufe, die man ansonsten leicht vergißt.
Die Windows-Programmierung ist asynchron. Es geschehen viele Dinge gleichzeitig. Wenn in älteren Windows-Versionen ein Teil einer Anwendung in einer Schleife oder auf andere Weise hängenblieb, blieb gleich die gesamte Anwendung û und manchmal sogar das gesamte System û hängen. Dies war offensichtlich ein Zustand, den es unter allen Umständen zu zu unterbinden galt. Ein Socket-Aufruf, etwa ein Aufruf, der über eine TCP/IP-Verbindung mit einem anderen Site des Internet das Lesen von Informationen erlaubt, kann für seine Ausführung einige Zeit in Anspruch nehmen. (Man spricht davon, daß eine Funktion, die auf das Senden oder Empfangen von Informationen wartet, blockiert.) Es gibt drei Möglichkeiten, um dieses Problem zu umgehen:
Möglichkeit 1 war bis vor kurzem noch nicht verfügbar, und Möglichkeit 2 ist unter Windows ineffizient. Daher hat sich für den größten Teil der Winsock-Programmierung die Möglichkeit 3 eingebürgert. Die Klasse CAsyncSocket implementiert diesen Ansatz. Um etwa eine Zeichenfolge über einen verbundenen Socket zu einer anderen Internet-Site zu senden, rufen Sie die Send-Funktion dieses Socket auf. Send muß nicht unbedingt Daten senden; vielmehr macht es den Versuch einer Datenübertragung, doch wenn der Socket nicht bereit ist, liefert es einen entsprechenden Rückgabewert. Ist der Socket bereit, wird dem Socket-Fenster eine Nachricht geschickt, das diese Nachricht abfängt und die Daten überträgt. Man nennt dieses Verfahren eine asynchrone Winsock-Programmierung.
Tabelle 18.1: Mitgliedsfunktionen der Klasse CAsyncSocket (Forts.)
Methode |
Beschreibung |
Accept |
Verarbeitet die an einem Socket in Wartestellung eingehende Verbindung und füllt einen neuen Socket mit der Adreßinformation. |
AsyncSelect |
Fordert das Senden einer Windows-Nachricht an, wenn ein Socket bereit ist. |
Attach |
Hängt einer CAsyncSocket-Instanz ein Socket-Handle an, so daß eine Verbindung zu einem anderen Rechner hergestellt werden kann. |
Bind |
Verbindet eine Adresse mit einem Socket. |
Close |
Schließt den Socket. |
Connect |
Verbindet den Socket mit einer entfernten Adresse und einem Port. |
Create |
Beendet den vom Konstruktor begonnenen Initialisierungsprozeß. |
Detach |
Entfernt ein zuvor angehängtes Socket-Handle. |
FromHandle |
Liefert einen Zeiger auf den mit dem angegebenen Handle verbundenen CAsyncSokket. |
GetLastError |
Liefert den Fehlercode des Socket. Durch Aufruf von GetLastError nach einer erfolglosen Operation können Sie den Grund des Fehlschlagens der Operation herausfinden. |
GetPeerName |
Ermittelt die IP-Adresse und Port-Nummer des entfernten Socket, mit der die aufrufende Objekt-Socket verbunden ist, oder füllt eine Socket-Adressenstruktur mit dieser Information. |
GetSockName |
Liefert die IP-Adresse und Port-Nummer dieses Socket oder füllt eine Sokket-Adressenstruktur mit dieser Information. |
GetSockOpt |
Liefert die aktuelle Einstellung der Socket-Optionen. |
IOCtl |
Setzt den Modus des Socket, meist auf blockierend oder nicht-blockierend. |
Listen |
Weist einen Socket an, auf eingehende Verbindungen zu warten. |
OnAccept |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn bei einem Socket eine zu akzeptierende Verbindung eingeht. Wird oft durch abgeleitete Klassen überschrieben. |
OnClose |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn ein Socket geschlossen wird. Wird oft durch abgeleitete Klassen überschrieben. |
OnConnect |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn zu einem Socket eine Verbindung aufgebaut wurde oder ein Verbindungsversuch fehlschlägt. Wird oft durch abgeleitete Klassen überschrieben. |
OnOutOfBandData |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn bei einem Socket wichtige Out-of-band-Daten eingegangen sind. |
OnReceive |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn bei einem Socket Daten eingegangen sind, die man mit Receive lesen könnte. Wird oft durch abgeleitete Klassen überschrieben. |
OnSend |
Verarbeitet die Windows-Nachricht, die generiert wird, wenn ein Socket bereit ist für die Annahme von Daten, die man mit Send versenden könnte. Wird oft durch abgeleitete Klassen überschrieben. |
Receive |
Liest Daten aus dem entfernten Socket, mit denen dieser Socket verbunden ist. |
ReceiveFrom |
Liest ein Datagramm aus einem verbindungslosen, entfernten Socket. |
Send |
Sendet Daten an den entfernten Socket, mit denen dieser Socket verbunden ist. |
SendTo |
Sendet ein Datagramm ohne eine Verbindung. |
SetSockOpt |
Dient zum Einstellen von Socket-Optionen. |
ShutDown |
Hält den Socket offen, verhindert jedoch weitere Send- oder Receive-Aufrufe. |
Wenn Sie die Klasse CAsyncSocket verwenden, werden Sie die Socket-Adressenstrukturen selbst ausfüllen müssen û doch würden viele Entwickler den Großteil dieser Arbeit gern delegieren. In diesem Fall ist CSocket die geeignetere Socket-Klasse.
CSocket: Die Klasse CSocket ist von CAsyncSocket abgeleitet und verfügt somit über alle für CAsyncSocket aufgelisteten Funktionen. In Tabelle 13.2 werden diese neuen Methoden beschrieben sowie die virtuellen Methoden, die in der abgeleiteten CSocket-Klasse überschrieben werden.
Tabelle 18.2: OnMessagePending Verarbeitet die Windows-Nachricht, die für andere Bereiche Ihrer Anwendung generiert wurde, während der CSocket-Methoden (Forts.)
Methode |
Beschreibung |
Attach |
Hängt einer CSocket-Instanz ein Socket-Handle an, so daß eine Verbindung zu einem anderen Rechner hergestellt werden kann. |
Create |
Beendet die Initialisierung, nachdem der Konstruktor einen leeren Socket erstellt hat. |
FromHandle |
Liefert einen Zeiger auf den mit dem angegebenen Handle verbundenen CSocket. |
IsBlocking |
Liefert den Wert TRUE, wenn der Socket gerade blokkiert ist und auf eine Aktion wartet. |
CancelBlockingCall |
Bricht die Anfrage ab, die den Socket blockiert hat. |
OnMessagePending |
Verarbeitet die Windows-Nachricht, die für andere Bereiche Ihrer Anwendung generiert wurde, während der Socket blockiert ist. Wird oft durch abgeleitete Klassen überschrieben. |
In vielen Fällen ist keine spezielle Socket-Programmierung mehr erforderlich, da die WinInet-Klassen, die ISAPI-Programmierung und ActiveX-Steuerelemente für Web-Seiten dem Internet-Programmierer immer mehr Leistung bereitstellen. Wenn Sie ein Beispiel-Socket-Programm erforschen wollen, probieren Sie einmal die mit Visual C++ gelieferten Programme Chatter und ChatSrvr aus. Suchen Sie im Hilfesystem nach einem der beiden Namen, oder öffnen Sie die Dateien auf der CD in den Orndern DevStudio\VC\Samples\MFC\Advanced\Chatter und DevStudio\VC\Samples\MFC\Advanced\Chatsrvr.
Jede Chatter-Sitzung emuliert einen Anwender-Server. Das Programm ChatSrvr ist der Server, der als Traffic-Manager zwischen verschiedenen Clients fungiert. Jeder Chatter kann an ChatSrvr Nachrichten senden û durch Eingabe von Text û, und ChatSrvr sendet die Nachricht an alle, die sich während dieser Sitzung angemeldet haben. Es werden mehrere Traffic-Channels gleichzeitig verwaltet.
Wenn Sie bereits mit Sockets gearbeitet haben, mag diese Kurzübersicht als Einstiegsinformation genügen. Wenn nicht, brauchen Sie es vielleicht nie zu lernen. Wenn Sie die Programmierung einer Client-/Server-Anwendung planen, die über das Internet ausgeführt wird, doch keine der vorhandenen Standardanwendungen wie E-Mail oder Web verwendet, so werden Sie sich künftig wohl mit dem Erlernen der Socket-Programmierung befassen müssen. Doch für den Einsatz von E-Mail, Web, ftp und anderen verbreiteten Internet-Informationsquellen brauchen Sie überhaupt keine Socket-Programme zu schreiben. Häufig können Sie für die erwünschten Ergebnisse MAPI, die WinInet-Klassen oder ISAPI verwenden.
Das beliebteste Netzwerk-Leistungsmerkmal ist in den meisten Büros die elektronische Post (E-Mail). Sie könnten Code in Ihre Anwendung aufnehmen, der über einen Socket die geeigneten Befehle generiert, um eine Mail-Nachricht zu übertragen, doch ist es wohl einfacher, auf die Arbeit anderer aufzusetzen.
MAPI (kurz für engl. Messaging Application Programing Interface) bietet eine Methode, Anwendungen, die Nachrichten senden und empfangen müssen (Messaging Applications), mit Anwendungen zu kombinieren, die wissen, wie Nachrichten gesendet und empfangen werden (Messaging Services und Service Provider). Dadurch wird die erforderliche Arbeit aller beteiligter Entwickler reduziert. In Abbildung 18.1 wird die Bandbreite des MAPI veranschaulicht. Beachten Sie, daß die Bezeichnung Messaging ein viel breiteres Spektrum abdeckt als nur das Versenden von E-Mails: Ein MAPI-Dienst kann etwa anstelle einer E-Mail auch ein Fax oder eine Voice-Mail-Nachricht senden. Wenn Ihre Anwendung die MAPI nutzt, werden die installierten Messaging-Dienste, z.B. E-Mail-Clients, das Senden der in Ihrer Anwendung erzeugten Nachrichten übernehmen.
Abbildung 18.1: Das Messaging-API deckt Anwendungen ab, die das Messaging-Merkmal benötigen, sowie Anwendungen, die es bereitstellen.
Eine Anwendung kann das Messaging-Leistungsmerkmal in vielfacher Weise nutzen:
Der Hautgrund für einen Entwickler, seine Anwendung messaging-erkennend zu konzipieren, ist oft, den Anforderungen für das Messaging-Anwendungen fuer das Windows-95-LogoWindows 95-Logo entgegenzukommen. Um den Richtlinien für dieses Logo zu entsprechen, muß eine Anwendung im Menü Datei den Befehl Nachricht senden besitzen, der unter Verwendung des MAPI das Dokument versendet. (Ausnahmen werden für dokumentenlose Anwendungen gewährt.)
Wenn Sie dieses Leistungsmerkmal in Ihre Anwendungen aufnehmen wollen, sollten Sie am besten daran denken, bevor Sie mit Hilfe des Anwendungs-Assistenten das Anwendungsgerüst erstellen. Für alle, die vorausplanen, ist hier eine Liste der Aufgaben, die Sie erledigen müssen, um diesen Teil der Logo-Anforderungen zu erfüllen:
Das war's! Der Menübefehl wird automatisch ergänzt, und die Nachrichtentabellen und Nachrichtenbearbeitungsfunktionen werden generiert. Diese dienen zum Abfangen des Menübefehls und der Aufruffunktionen, die die Funktion Serialize Ihrer Anwendung benutzen, um das Dokument über das MAPI zu übertragen. In Abbildung 18.2 sehen Sie eine Anwendung mit dem Namen MAPIDemo, die auch auf der CD-ROM zu diesem Buch zu finden ist. Hierbei handelt es sich einfach um ein Programm, das vom Anwendungs-Assistenten generiert wird, wenn die MAPI-Option aktiviert wird.
Abbildung 18.2: Der Anwendungs-Assistent ergänzt das Menü Datei automatisch um den Befehl Nachricht senden und fügt den Code ein, der die Reaktion auf den Befehl regelt.
Abgesehen von dem vom Anwendungs-Assistenten generierten Code brauchte für diese Anwendung kein Code geschrieben zu werden. Und wie Sie sehen, wurde in das Menü Datei der Befehl Nachricht senden aufgenommen. Wenn Sie diesen Menübefehl auswählen, wird Ihr MAPI-Mail-Client geladen, damit Sie die Nachricht versenden können. Die Abbildungen 18.2 und 18.3 stammen von einem System, bei dem Microsoft Exchange als Internet-Mail-Client installiert wurde. Es wird also Microsoft Exchange geladen (vgl. Abbildung 18.3). Die Nachricht umfaßt das aktuelle Dokument, und Sie brauchen nur noch Empfänger, Betreff und Text eingeben, der zusammen mit dem Dokument gesendet werden soll.
Abbildung 18.3: Microsoft Mail wird geladen, so daß der Anwender um das gesendete Dokument den Rest der E-Mail-Nachricht eintragen kann.
Wenn Sie beim Erstellen der Anwendung im Anwendungs-Assistenten keine MAPI-Unterstützung angefordert haben, können Sie den Befehl Nachricht senden auch nachträglich hinzufügen. Dazu führen Sie folgende Arbeitsschritte aus:
ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail)
ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail)
Die Mail-Unterstützung manuell in eine Anwendung aufzunehmen, ist nicht viel schwieriger, als es vom Anwendungs-Assistenten ausführen zu lassen.
Wenn Sie aus MAPI mehr herausholen wollen, als die Anforderungen für das Windows-Logo verlangen, wird die Sache schon etwas schwieriger. Im Prinzip gibt es vier Arten von MAPI-Client-Schnittstellen:
Die Header-Datei XCMC.H deklariert eine Reihe von Strukturen für die Aufnahme der Informationen, die an diese Funktionen übergeben werden. Empfängerinformationen werden beispielsweise in der folgenden Struktur gespeichert:
/*RECIPIENT*/
typedef struct {
CMC_string name;
CMC_enum name_type;
CMC_string address;
CMC_enum role;
CMC_flags recip_flags;
CMC_extension FAR *recip_extensions;
} CMC_recipient;
Sie könnten diese Struktur mit dem Namen und der Adresse des Empfängers einer Mail-Nachricht ausfüllen, indem Sie ein Standarddialogfeld verwenden oder die Einträge wie folgt fest programmieren:
CMC_recipient recipient = {
"Kate Gregory",
CMC_TYPE_INDIVIDUAL,
"SMTP:kate@gregcons.com",
CMC_ROLE_TO,
CMC_RECIP_LAST_ELEMENT,
NULL };
Type, Role und Flags verwenden einen der folgenden vordefinierten Werte:
Listing 18.1: Befehlsdefinitionen (Auszug aus der zu Visual C++ gehörenden Datei XCMC.H) |
* NAME TYPES */
#define CMC_TYPE_UNKNOWN ((CMC_enum) 0)
#define CMC_TYPE_INDIVIDUAL ((CMC_enum) 1)
#define CMC_TYPE_GROUP ((CMC_enum) 2)
/* ROLES */
#define CMC_ROLE_TO ((CMC_enum) 0)
#define CMC_ROLE_CC ((CMC_enum) 1)
#define CMC_ROLE_BCC ((CMC_enum) 2)
#define CMC_ROLE_ORIGINATOR ((CMC_enum) 3)
#define CMC_ROLE_AUTHORIZING_USER ((CMC_enum) 4)
/* RECIPIENT FLAGS */
#define CMC_RECIP_IGNORE ((CMC_flags) 1)
#define CMC_RECIP_LIST_TRUNCATED ((CMC_flags) 2)
#define CMC_RECIP_LAST_ELEMENT ((CMC_flags) 0x80000000)
Es gibt eine Nachrichtenstruktur, die Sie auf dieselbe Weise ausfüllen könnten bzw. vom Anwender ausfüllen lassen, indem Sie diesem ein Dialogfeld mit den entsprechenden Nachrichteninformationen präsentieren. Diese Struktur enthält einen Zeiger auf die Empfängerstruktur, die Sie bereits ausgefüllt haben. Ihr Programm ruft dann cmc_logon, cmc_send und cmc_logoff auf, um den Vorgang abzuschießen.
Active-Messaging: Wenn Sie die Automation verstehen (vgl. Kapitel 16, »Einen Automations-Server entwickeln«) verstehen Sie auch schnell das Active-Messaging. Ihre Anwendung muß jedoch ein Automations-Client sein, und das Erstellen eines solchen Client liegt jenseits der Thematik dieses Kapitels. Einige Möglichkeitein für das Active-Messaging bestehen im Einsatz der Visual Basic-Programmierung und von VBA-Skripten für Programme wie Excel. Ihr Programm würde Objekte einrichten und dann ihre bereitgestellten Eigenschaften einstellen (z.B. die Zeile Betreff in einem Nachrichtenobjekt) und die bereitgestellten Methoden aufrufen (bei einem Nachrichtenobjekt etwa die Methode Send).
Folgende Objekte werden beim Active-Messaging verwendet:
Eine ausführliche Referenz dieser Objekte sowie ihrer Eigenschaften und Methoden finden Sie im Hilfesystem des Developer Studio.
Mit den MFC 4.2 wurde eine Reihe neuer Klassen vorgestellt, die das Erlernen der Socket-Programmierung unnötig machten, wenn die Anwendungen nur auf Standard-Internet-Client-Dienste zugreifen mußten. In Abbildung 18.4 sehen Sie, wie diese Klassen zusammenhängen. Diese unter dem Sammelbegriff WinInet-Klassen bekannten Klassen sind die Folgenden:
Abbildung 18.4: Die WinInet-Klassen erleichtern das Schreiben von Internet-Client-Programmen.
Zunächst richtet Ihr Programm eine Sitzung ein, indem eine CInternetSession erstellt wird. Und wenn Sie die URL-Adresse Ressourcen abrufen ueber die Funk(Uniform Resource Locator) zu einer Gopher-, FTP- oder Web-(HTTP-)Ressource haben, können Sie die Funktion OpenURL dieser Sitzung aufrufen; dadurch wird die Ressource als CInternetFile im Lesemodus abgerufen. Ihre Anwendung kann die Datei mit Hilfe von CStdioFile-Funktionen lesen und diese Daten in der gewünschten Weise manipulieren.
Wenn Sie die URL nicht kennen oder eine Datei nicht nur im Lesemodus abrufen wollen, ist das weitere Vorgehen nach dem Sitzungsaufbau unterschiedlich. Sie stellen die Verbindung mit einem spezifischen Protokoll her, indem Sie die Funktionen GetFtpConnection, GetGopherConnection oder GetHttpConnection dieser Sitzung aufrufen, die das entsprechende Verbindungsobjekt liefern. Dann rufen Sie die Funktion OpenFile der Verbindung auf. CFtpConnection::OpenFile liefert eine CInternetFile; CGopherConnection::OpenFile liefert eine CGopherFile und CHttpConnection::OpenFile liefert eine CHttpFile. Die Klasse CFileFind und die von ihr abgeleiteten Klassen helfen beim Auffinden der zu öffnenden Datei.
Kapitel 19, »Internet-Programmierung mit den WinInet-Klassen«, stellt ein Beispiel-Client-Programm vor, das mit Hilfe der WinInet-Klassen eine Internet-Sitzung aufbaut und Informationen abruft.
Mit Hilfe von ISAPI lassen sich die Fähigkeiten Ihres HTTP-Servers (WWW-Servers) verbessern und erweitern. ISAPI-Entwickler erstellen Erweiterungen und Filter. Erweiterungen sind DLLs, die vom Anwender von einer Web-Seite aus aufgerufen werden, in ähnlicher Weise wie CGI-Anwendungen von Web-Seiten aus aufgerufen werden. Filter sind DLLs, die mit dem Server zusammen ausgeführt werden und die ein- und ausgehenden Daten beobachten oder ändern. Beispielsweise kann ein Filter Anfragen für eine Datei zu einer neuen Web-Adresse umleiten.
Damit die von Ihnen programmierten ISAPI-Erweiterungen und -Filter auch praktisch einsetzbar sind, müssen Ihre Web-Seiten auf einem ISAPI-konformen Server, wie etwa dem Microsoft IIS Server, gespeichert sein. Zudem müssen Sie die geeigneten Rechte besitzen, um DLLs auf diesem Server installieren zu dürfen, und für ISAPI-Filter müssen Sie die Möglichkeit haben, die Registrierung auf dem Server zu ändern. Sind Ihre Web-Seiten auf einem Rechner gespeichert, der von Ihrem Internet Service Provider (ISP) verwaltet wird, so werden Sie vermutlich nicht in der Lage sein, ISAPI zur Verbesserung Ihrer Web-Seiten einzusetzen. Eine Möglichkeit wäre, Ihre Seiten auf einen konformen Server zu verlagern (ein leistungsstarker Intel-Rechner, auf der Windows NT Server 4.0 und Microsoft IIS ausgeführt werden, wäre eine gute Wahl), damit Sie ISAPI verwenden können. Doch ist diese Möglichkeit auch mit beträchtlichen Ausgaben verbunden. Informieren Sie sich auf jeden Fall über die Einschränkungen Ihres aktuellen Web-Servers, bevor Sie versuchen, ein Projekt mit Hilfe von ISAPI zu realisieren.
Die folgenden fünf MFC-ISAPI-Klassen bilden einen Wrapper für das API:
Ihre Anwendung wird eine Server- oder Filterklasse (oder beides) besitzen, die von CHttpServer bzw. CHttpFilter abgeleitet ist. Beide gleichen den Klassen in einer normalen Anwendung, die von CWinApp abgeleitet sind. In jeder DLL gibt es nur eine Instanz der Klasse, und jede Interaktion des Server mit einem Client geschieht durch seine eigene Instanz der entsprechenden Kontextklasse. (Eine DLL kann sowohl einen Server als auch einen Filter enthalten, doch jeweils höchstens einen.) CHtmlStream ist eine Hilfsklasse, die einen HTML-Strom beschreibt, der von einem Server zu einem Client gesendet wird.
Der ISAPI-Erweiterung Wizard ist ein Anwendungs-Assistent, der Sie beim Erstellen von Erweiterungen und Filtern unterstützt. Um diesen Assistenten einzusetzen, wählen Sie wie immer im Developer Studio Datei/Neu, und öffnen das Register Projekte. Markieren Sie den Listeneintrag Assistent für ISAPI-Erweiterungen (siehe Abbildung 18.5), tragen Sie den Projektnamen und Ordner ein, und klicken Sie auf OK.
Abbildung 18.5: Der Assistent für ISAPI-Erweiterungen dient zum Erstellen von Erweiterungen und Filtern.
Abbildung 18.6: Im ersten Schritt des Assistenten für ISAPI-Erweiterungen geben Sie die Namen der Komponenten der zu erstellenden DLL an.
Wenn Sie sich für das Erstellen eines Filters entscheiden, wird die Schaltfläche Weiter aktiviert, so daß Sie die zweite Seite für Erstellung von Filtern aufschlagen können (siehe Abbildung 18.7). Allein diese Parameterliste verschafft Ihnen einen Eindruck von der Leistungsvielfalt eines ISAPI-Filters. Sie können alle ein- und ausgehenden Anfragen und unformatierten Daten, die Zugangsberechtigung eines Anwenders (Echtheitsbestätigung) sowie Eintragungen in das Server-Protokoll überwachen lassen.
Abbildung 18.7: Im ersten Schritt des Assistenten für ISAPI-Erweiterungen können Sie die Eigenschaften des Filters bestimmen.
Bevor die Dateien erzeugt werden, wird noch einmal eine Zusammenfassung eingeblendet, die Sie bestätigen müssen. Wenn Sie einen Server und einen Filter gleichzeitig anlegen, werden elf Dateien erzeugt, einschließlich der Quelldateien für die Klassen, die von CHttpServer und CHttpFilter abgeleitet wurden.
Das Programmieren eines Filters auf der Grundlage dieses Gerüsts ist recht einfach. Ihr Programm wurde mit einem Funktionsgerüst ausgestattet, damit es auf jedes Ereignis reagieren kann, für das eine Benachrichtigung angefordert wurde. Die Filterklasse besitzt beispielsweise die Funktion OnEndOfNetSession, die aufgerufen wird, wenn eine Client-Sitzung mit diesem Server beendet wird. In diese Funktion fügen Sie den Code zum Protokollieren, Überwachen oder sonstigen Reagieren auf dieses Ereignis ein. Ist der Filter fertig, so ändern Sie die Registrierung manuell so ab, daß der Server Ihre DLL ausführt.
Was diese Funktion nun genau macht, hängt von Ihrer Anwendung ab. Angenommen, Sie implementieren ein Online-Bestellsystem, so sind umfangreiche und komplexe Funktionen erforderlich. Andere Erweiterungen wiederum sind einfacher.
Ist Ihre Funktion fertig programmiert, plazieren Sie die DLL in dem ausführbaren Ordner Ihres Servers û in der Regel der Ordner, in dem auch CGI-Programme gespeichert werden û und fügen folgende Links in Ihre Web-Seiten ein, wenn die Erweiterung aufgerufen werden soll:
Hier können Sie <A HREF=http://www.company.com/exec/orders.dll> Ihre Bestellung </A> aufgeben!
Die Miteinbeziehung des Internet in Ihre Anwendungen ist ein aufregender Trend. Für die Programmier bedeutet es viel Arbeit bei der Entwicklung leistungsfähiger Produkte, die allen Internet-Anwendern das Arbeitsleben erleichtern. Noch vor nur einem Jahr bedeutete die Programmierung von Internet-Anwendungen Ärmel hochkrempeln und Sockets-Zugänge programmieren, TCP/IP-Ports memorieren und RFCs lesen. Die neuen WinInet- und ISAPI-Klassen sowie Verbesserungen der alten MAPI-Unterstützung bedeuten für Sie, daß Sie durch wenige Zeilen Programmcode oder die Auswahl einer Option in einem Assistenten-Dialogfeld Ihre Anwendungen durch eine erstaunliche Leistungsvielfalt bereichern können.
Mehr über den Einsatz der in diesem Kapitel vorgestellten APIs und über das Erstellen anderer, spezifischer Anwendungen erfahren Sie in den folgenden Kapiteln: