Ein neues Netzwerk-API für Windows
Windows-Steckdose
Unter Windows wird KOMMUNIKATION gross geschrieben. Kein Wunder, dass kürzlich auch für den weit verbreiteten TCP/IP-Standard ein spezifisch auf Windows zugeschnittenes API aus der Taufe gehoben wurde. Dieses berücksichtigt die Idiosynkrasien des Fast-Multitasking-Systems Windows und öffnet dem Windows-Entwickler die Tür zur weiten Welt der heute so vielbeschworenen Client-Server-Programmierung.
Wer ist Client, wer Server?
Heute ist oft vom "Server" die Rede, als ob es sich um eine spezifische Maschine handelt. Dabei sind "Client" und "Server" eigentlich Softwarekonzepte, die nicht an Maschinen gebunden sind. Das heute ach-so-moderne Client-Server-Konzept geht von einem Netzwerk aus, wo verschiedene Knoten für spezielle Dienste (Services) zuständig sind. Bezüglich einer spezifischen Dienstleistung nennt man die Partei, welche die Dienstleistung erbringt, "Server" und den Bezüger der Dienstleistung "Client".
In der heute Novell-dominierten Netzwerkwelt hat sich die die Bezeichnung "Server" für den grossen zentralen Rechner im Netzwerk eingebürgert, weil dieser die wichtigste Novell-Netzwerk-Funktion des Diskservers erfüllt. Auf ähnliche Weise wurde früher die "Host"-"Guest"-Beziehung hypostasiert: ein "Host" konnte nur ein IBM- (oder DEC-) Mainframe sein.
Schon ein X-Windows-Produkt kehrt aber die Verhältnisse um: der Terminal (PC) bietet der Aussenwelt Bildschirmdarstellungsdienste an und ist daher ein X-Server für die X-Windows-Programm-Klienten, die bei ihm anklopfen.
Man kann heute bei der zunehmenden Vernetzung zwei Trends beobachten: Die Entwicklung zu zentralistischen Netzwerken einerseits und zu verteilten "Peer-to-Peer"-Netzwerken andererseits.
In zentralistischen Netzwerkwelten erlebt die sternförmige Rollenverteilung Mainframe-Terminal eine Renaissance. Der "Server" ist tatsächlich Server für fast jede erdenkliche Netzwerk-Dienstleistung (Disk, Drucker, Telekommunikation, Mail, Filetransfer...) und der "Client" verkommt zum (im Extremfall: disklosen) Terminal, der ohne "Server" nicht einmal mehr elementarste Funktionen eigenständig übernehmen kann.
In sogenannten "Peer-to-Peer"-Netzwerk-Architekturen hat man aus der Vergangenheit gelernt, dass der Ausfall eines einzelnen zentralen "Hosts" Hunderte von Arbeitsplätzen lahmlegen kann. In verteilten Netzwerken sind darum die Dienste auf verschiedene Maschinen verteilt, jeder Knoten kann auch unabhängig von ausgefallenen anderen Knoten unter Verzicht auf die ausgefallene Dienstleistung weiterarbeiten. Grundsätzlich kann jeder Knoten jede Dienstleistung übernehmen. So kann etwa der eine PC-Benutzer im Netz "Diskserver" für jeden anderen spielen. Er kann sich sogar gleichzeitig in der "Client"-Rolle den Disk eines anderen PCs als Netzwerkdisk "anschnallen". Das Paradebeispiel für eine real existierende verteilte Netzwerkarchitektur dürften die in der UNIX-Welt populären TCP/IP-Dienste darstellen.
TCP/IP ist zum Markenzeichen und Sammelbegriff verschiedenster Netzwerkdienste geworden, obwohl es sich ursprünglich um die Namen spezifischer Protokollschichten in diesen Netzwerken handelt. Hier soll nicht zum zigsten Mal im c't das OSI-Schichtenmodell erklärt werden. Zur Orientierung und als Glossar leistet die abgebildete Graphik von Prof. Manfred Bues hervorragende Dienste1.
Neuer Standard
Nachdem es schon für sehr heterogene Hardware/Betriebssystem-Kombinationen sogenannte "Sockets"-Interfaces gibt, ist kürzlich auch für MS-Windows ein solcher neuer Standard erschienen2. Der neue Standard wird von Microsoft mitgetragen, was ihm eine gewisse Überlebenschance sichert.
Ein standardisiertes API ist im wesentlichen eine Schnittstelle. In diesem Fall handelt es sich um die Schnittstelle zwischen API-Benutzern, nämlich Anwendungsprogrammen, die Netzwerkservices benötigen und zwischen API-Anbietern von Netzwerkprodukten. Der Erfolg und die Durchsetzungskraft eines neuen Standards kann abgelesen werden an der Anzahl Anbieter dieses API als auch an dem Einsatz dieses API durch gewichtige Benutzer.
Unter den API-Anbietern war das Produkt Super-TCP von Frontier Technologies Corp. wohl allen Konkurrenten eine Nasenlänge voraus. Sun, der gewichtigste Anbieter von TCP/IP-Software für den PC, hat allerdings die Unterstützung des neuen API mit der Verson 5.0 ihres Produkts PC-NFS auch schon angekündigt und somit den Geltungsbereich des neuen Standards auf API-Anbieterseite konsolidiert.
Die wichtigen API-Benutzer, wie Oracle und SyBase haben ihre Anwendungen nun meistens mit Hilfe von Super-TCP ausgetestet und kündigen ringsum ihre neue "Compliance" mit dem "Windows Sockets API" an. Im folgenden wird vorgeführt, wie man als Windows-Benutzer ganz leicht selber zum API-Benutzer werden kann.
Erst den kleinen Finger ...
Unsere Kunden interessieren sich für die Netzwerkintegration heterogener Systeme. Darum haben wir seit einiger Zeit eine Lizenz von Super-TCP von Frontier Technologies Corp. zur Verfügung. Dieses enthält das Windows Sockets API in Form einer Dynamischen Link Library namens WINSOCK.DLL.
Um nun eigene Netzwerkanwendungen zu programmieren, benötigt man Information, eine das API verkörpernde Include-Datei WINSOCK.H und möglichst eine für die DLL zuständige Importlibrary WINSOCK.LIB.
Information über die Programmierung des Windows Sockets API fanden wir in einem Artikel in einer Computerzeitschrift.3 Wir setzten uns zum Ziel, als erstes das dort beschriebene "Finger-Client-Server"-Programm in Borland C++ zu implementieren. Dem Artikel entnahmen wir auch, dass die Windows Sockets Spezifikation über Netzwerk erhältlich ist4. Ein hilfreicher Freund5 hatte die notwendigen Dateien am nächsten Tag schon beschafft. Das vom Netzwerk herabgeladenen WINSOCK.ZIP enthielt die PostScript-Datei WINSOCK.PS und die Include-Datei WINSOCK.H. Unser OKI-OL800 bewies, dass er ein richtiger PostScript-Drucker ist: Der Befehl copy winsock.ps prn reichte aus, um ein schön formatiertes Exemplar des Standards zu drucken.
Der Standard beschreibt das Windows Sockets API und geht insbesondere auf die speziellen Windows-Idiosynkrasien ein. Während die klassischen UNIX-Calls, welche Daten empfangen, den Process blockieren, hat man unter Windows die Möglichkeit, statt dessen anzugeben, welchem Fenster welche Windows-Meldung zu schicken ist, und kann unblockiert weiterarbeiten.
Zur erfolgreichen Implmentation des Finger-Programms fehlte also nur noch die Import-Library. Diese ist in ihrer Struktur zwar in der Spezifikation ausführlich beschrieben, ein einfaches IMPLIB aus der Borland-Trickkiste angewendet auf die WINSOCK.DLL von Frontier löste das Problem aber schneller und bequemer.
Ein "finger" ist in der UNIX-Tradition ein Programm, dass Zusatzinformation über einen Benutzer an einem anderen Rechner erfragt. Unser Beispielprogramm implementiert sowohl einen "Client" als auch einen "Server". Alles Windows-Sockets-Spezifische spielt sich im Modul MAINWIN ab. In den Methoden SetupWindow und ShutdownWindow wird der Kontakt mit der Netzwerksoftware aufgenommen bzw. abgebrochen. Vor Beendung des Programms werden offene "Sockets" geschlossen.
Unter einem "Socket" ist eine Internet-Adresse zusammen mit einer Portnummer zu verstehen. Alle diese TCP/IP-Interna findet man heute leicht in der einschlägigen Literatur. Einen exzellenten, knappen Einstieg in klarem Deutsch bietet etwa Lukas T. Gorys in seinem Arbeitsbuch6.
Der "Finger-Client" ist in der Prozedur CMClient() implementiert. Er fragt in einer Dialogbox nach Host und Usernamen und bestimmt die entsprechende Internet-Adresse, indem im lokalen Hosts-Verzeichnis nachgesehen wird. Auch die Portnummer der "well-known" Finger-Anwendung wird per Lookup bestimmt. Aus diesen Angaben wird das Socket zusammengezimmert und mit Hilfe von connect() auf die Suche nach seiner passenden Steckdose im Netzwerk geschickt. Wenn die Verbindung zustande gekommen ist, habe wir jetzt eine dem DDE-Link vergleichbare Verbindung zu einem Finger-Server auf dem gewählten Host. Diesem schicken wir nun unseren Request (Username) um mehr Information mittels send() und warten auf die Antwort mit recv().
In diesem Fall ist diese Funktion "blockierend", weil wir sofortige Antwort erwarten. Sollte trotzdem einmal keine Antwort reinkommen, können wir den "Finger-Client" mit dem Cancel-Befehl vom Menü aus "abschiessen". Dieser ist in der Funktion CMCancel() implementiert und ruft die Funktion WSACancelBlockingCall() des API auf.
Der "Finger-Server" ist ähnlich einfach gebaut. Da der Server noch nicht weiss, mit welchem Host er reden wird, wird die Adresse mit der Konstanten INADDR_ANY initialisert. Mit bind() binden wir den Server-Socket an den Fingerport. Schliesslich geben wir ihm mit listen die Aufgabe auf sämtliche Aktivität auf diesem Port zu reagieren. Die Funktion WSAAsyncSelect() gibt an, welche Meldung geschickt werden soll, wenn sich ein Client an unserem Port meldet. Die Fortsetzung des Servers findet man in der Methode UMConnect, die von der WINSOCK.DLL aktiviert wird, wenn ein Client einen connect() versucht. Mittels accept() wird die Verbindung auf der Serverseite festgemacht. Das Link besteht nun zwischen dem Socket fconnect des Servers und dem Socket fclient des Client, während das Socket fserver weiter auf Aktivität am Fingerport hört. Für die neue Verbindung rufen wir wieder die Funktion WSAAsyncSelect(), und lassen uns die Meldung UM_DATA schicken, wenn sich auf dem Link etwas tut. In diesem Fall kommt in unserem Programm die Methode UMData() an die Reihe. Diese empfängt die Daten und schickt den vorher über eine Dialogbox eingelesenen Informationstext an den Client.
Das Finger-Beispiel ist insofern eine nicht-triviale Anwendung des Windows Sockets API, als es sich um eine volle Server und Client Anwendung handelt. Es funktioniert mit einem UNIX-Finger-Dämon auf der anderen Seite, mit einer Kopie von sich selbst als Partner oder etwa mit dem mit Super-TCP mitgelieferten Finger-Client. Damit es ein akzeptables Produkt wird, müsste allerdings noch einige Aufräumarbeit geleistet werden.
...dann die ganze Hand
Die klassischen TCP/IP-Services werden im Allgemeinen wohl schon vom Lieferanten der Netzwerk-Software mitgeliefert (FTP, NFS, SMTP, Mail, ...). Die klassischen Transaktionsverarbeiter haben das API schon in Betrieb genommen. Für sie stellt das Windows Sockets API einfach ein weiteres Sockets-API dar, wie für zig andere Umgebungen. Für Windows-Entwickler eröffnet sich mit diesem API allerdings eine Vista von sehr hübschen Möglichkeiten, welche die für Windows typische Ausdruckskraft deutlich erhöht.
Zum Beispiel wäre es ein leichtes, ein Client/Server-Paar zu schreiben, welches DDE-Meldungen via TCP auf fremden Rechnern weiterleitet und somit für eine Erweiterung des DDE-Äthers sorgt. Die Teilnehmer an einer DDE-Konversation müssten nicht mehr auf demselben Rechner residieren. An bestehenden DDE-Dialogen müsste nichts verändert werden und schon wären sie "netzwerkfähig".
Auch die Möglichkeit OLE-Server für auf verschiedene Knoten verteilte OLE-Dokumente zu bauen eröffnet eine ganze Reihe von Perspektiven...
31.3.1993 Hartwig Thomas
Programm und Quellen
Das Finger-Projekt basiert auf Borland-C++.
Finger Executable (Win16, auf allen Win32-Plattformen lauffähig): finger.exe
Finger Projektdatei: finger.prj
Finger DEF-Datei: finger.def
Finger Windows Ressourcen: finger.rc
Finger Icon: finger.ico
Finger C++ Headerdatei: (globale Konstanten) finger.h
Finger C++ Quelldatei: finger.cpp
Mainwin C++ Headerdatei: mainwin.h
Mainwin C++ Quelldatei: mainwin.cpp
Dialogs C++ Headerdatei: dialogs.h
Dialogs C++ Quelldatei: dialogs.cpp
Winsock C++ Headerdatei: winsock.h
Winsock Static Library: winsock.lib
Winsock DEF-Datei: winsock.def
Winsock Dokumentation (PostScript): winsock.ps
Fussnoten
1 SVD/VDF-Tagung: Prof. Manfred Bues: Offene Systeme, Herausforderung für das Informatik-Management, 11.3.93, Tagungsdokumentation
2 Martin Hall (JSB Corporation), Mark Towfiq (FTP Software Inc.), Geoff Arnold (Sun Microsystems, Inc.) David Treadwell (Mircosoft Corporation), Henry Sanders (Microsoft Corporation): Windows Sockets, An Open Interface for Network Programming under Microsoft Windows, Version 1.0 Rev. B, 16 June 1992
3 Mike Calbaum, Frank Porcaro, Mark Ruegsegger, Bruce Backman (alle von Frontier Technologies Corp.): Untangling the Windows Socktes API, A standardized interface for network development, Dr. Dobb's Journal, Feb. 1993
4 Anonymes ftp von vax.ftp.com oder ftp.uu.net; oder via CompuServe aus den Microsoft Software Libraries (GO MSL)
5 Christian d'Heureuse, Inventec Informatik AG, Zürich
6 Lukas T. Gorys: TCP/IP Arbeitsbuch, Kommunikationsprotokolle zur Datenübertragung in heterogenen Systemen, Hüthig Buch Verlag Heidelberg, 1989