Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Kommunikation in Netzwerken mit Delphi 1. Grundlagen 1.1.Protokolle Regeln, nach denen die Kommunikation zwischen Computersystemen abläuft, werden als Protokolle bezeichnet. IP Protokoll Das Internet Protocol (IP Protokoll) ist das Basisprotokoll des Internet und regelt die Kommunikation zwischen den Netzwerkrechnern auf der Basis von Datenpaketen. Das IP Protokoll ist verbindungslos: Zwischen Sender und Empfänger besteht keine virtuelle Verbindung. Es ist paketorientiert: Daten werden in Form von Datagrammen übertragen, das sind Pakete, die die Nutzinformationen, weiter Kontrollinformationen, die Zieladresse sowie Informationen über das verwendete höhere (s.u.) Kommunikationsprotokoll enthalten. Das IP Protokoll ist unsicher: Es gewährleistet nicht, dass die Datagramme beim Empfänger auch ankommen. Alle anderen höheren Protokolle bauen auf diesem IP Protokoll auf, z. B. TCP Protokoll Im Gegensatz zum IP Protokoll ist das Transmission Control Protocol (TCP Protokoll) ein verbindungsorientiertes und sicheres Protokoll. Verbindungsorientiert bedeutet: Bevor Daten zwischen zwei Netzwerk-Rechnern ausgetauscht werden können, muss eine virtuelle Verbindung aufgebaut werden. Sicher bedeutet: Der Empfänger kontrolliert die eingehenden Datagramme auf Vollständigkeit und Fehlerfreiheit und meldet diese Informationen an den Sender zurück. Bleibt beim Sender diese Bestätigung aus, sendet er sie erneut. UDP Protokoll Das User Datagram Protocol (UDP Protokoll) ist ein im Gegensatz zum TCP Protokoll verbindungsloses und unsicheres Protokoll: Es sorgt weder dafür, dass die Datenpakete ihren Empfänger erreichen, noch dass sie ihren Empfänger in der richtigen Reihenfolge erreichen. Der Vorteil des UDP Protokolls gegenüber dem TCP Protokoll besteht darin, dass weniger Zusatzinformationen übertragen werden. Es eignet sich für Anwendungen, bei denen geringe Störungen kaum wahrnehmbar sind (z. B. Streaming-Video, Streaming-Audio): Fehlende Informationen werden einfach weggelassen. 1.2 Sockets Sockets sind standardisierte Schnittstellen für die Kommunikation zwischen Rechnern mit TCP/IP. In der Windows-Welt entstanden verschiedene Versionen des WinSock-API (Application Programming Interface), eine Sammlung sämtlicher Routinen für die Rechnerkommunikation mittels IP Protokollen (z. B. TCP oder UDP). Früheren Windows1 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Versionen wurden die benötigten Dateien manuell (z. B. WinSock32) hinzugefügt, in neueren Versionen des Betriebsystems) sind diese Routinen integraler Bestandteil des Betriebssystems. Der Name Socket (dt. Stecker) ist Programm: Das Server-Programm besitzt einen "Stecker" (eigentlich eine Steckdose), in die dann sich ein Client-Programm "andocken" kann. Der Client-Stecker wird beim Anmelden mit dem Server-Programm über diese Steckdose verbunden. Durch das Verbindungskabel findet der Datenaustausch statt. 1.2.1 Kommunikation über Sockets Will ein Client-Prozess (Rechner, Programm ... ) mit einem Server-Prozess mittels solcher Sockets kommunizieren, muss er einen Socket erzeugen, dem Socket bei Bedarf einen eigenen Port zuweisen, den Socket mit einem anderen (Server-) Socket verbinden, Daten über diese Sockets austauschen, den Socket am Ende der Kommunikation wieder schließen und freigeben. Ein Server-Prozess muss nun, damit der Client ihn finden kann: einen Socket erzeugen und öffnen, diesem eine Adresse zuweisen (IP Adresse + Port-Nummer), mit diesem auftretende Verbindungsanforderungen empfangen, jedem Client, der sich anmeldet, einen weiteren Socket für die Kommunikation zur Verfügung stellen, diesen speziellen "Verbindungs-Socket" wieder freigeben, wenn der Prozess endet.. Wird nun vom Server-Prozess eine solche Verbindungsanforderung empfangen, muss er also einen weiteren Socket für die Datenkommunikation erzeugen, mit diesem dann Daten zum Client senden oder Daten vom Client empfangen, diesen Socket wieder entfernen, wenn die Kommunikation mit dem Client-Prozess beendet ist. Vereinfachend kann man also sagen, dass ein Socket-Server sich von einem Socket-Client darin unterscheidet, dass der Server-Prozess vor Kontaktaufnahme läuft und hierbei einen Socket für die Kontaktaufnahme zur Verfügung stellt, den der Client für seine Kontaktaufnahme ansprechen kann, dass er ferner mehrere Sockets verwalten kann, damit er zeitgleich unterschiedliche Clients bedienen kann (z. B. Chat-Server). 2 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Ein Socket ist also ein Kommunikationsendpunkt (ein Objekt), durch das Datenpakete sowohl gesendet als auch empfangen werden (bidirektionaler Datenfluss). Man unterscheidet dabei zwei verschiedene Typen von Sockets: Streamsockets (TCP Sockets = Transmission Control Portocol) Datagrammsockets (UDP Sockest = User Datagramm Protocol) 1.2.2 Streamsockets Sockets des Typen Streamsocket sind verbindungsorientiert und zuverlässig. Verbindungsorientiert bedeutet in diesem Fall, dass zwischen den beiden beteiligten Prozessen stets eine feste Verbindung gegeben ist. Diese feste Verbindung bei der Kommunikation gewährleistet, dass ein kontinuierlicher Datentransport in Form eines „ByteStroms“ vorhanden ist, was vor allem den Transport von besonders großen Datenmengen ermöglicht. Vergleichbar mit einer Standleitung, besteht die kontinuierliche Verbindung bis einer der beiden Kommunikationspartnern die Verbindung beendet und somit den Datenaustausch unterbricht. Die Zuverlässigkeit der Streamsockets ergibt sich dadurch, dass bei jedem Datenaustausch die gesendeten Daten garantiert in der abgesendeten Reihenfolge ankommen. Die Kommunikation anhand der Steamsockets ist mit einem Telefonat zu vergleichen und ist den Datagrammsockets vorzuziehen wenn der Datenempfang unbedingt gewährleistet sein muss und große Datenmengen übertragen werden. Das Internet basiert z. B. auf diesem Sockettyp anhand des TCP/IP Protokolls. 1.2.3 Datagrammsockets Im Gegensatz zu den Streamsockets sind Datagrammsockets verbindungslos und garantieren keine Zuverlässigkeit. Die Kommunikation anhand der Datagrammsockets erfolgt anhand des Versand von Paketen. Da zwischen den Kommunikationspartnern keine feste Verbindung besteht, muss jedes verschickte Datenpaket mit der Adresse des Empfängers versehen sein. Greift man beim Datenaustausch nun auf Datagrammsockets zurück, so wird nur das Absenden der Datenpakete garantiert, der Empfang und die richtige Reihenfolge können jedoch unter Umständen fehlerhaft sein. Ein Beispiel für die Verwendung von Datagrammsockets ist die Anfrage an einen Server: Erfolgt nach kurzer Zeit keine Antwort, so wird erneut ein Datenpaket, welches die Zieladresse beinhaltet, losgeschickt. Ein weiteres Beispiel für die Verwendung von Datagrammsockets ist die Synchronisierung vom Systemuhren im Netzwerk. Kurz formuliert liegt die Stärke von Datagrammsockets darin, eine Meldungsübertragung an eine große Anzahl an Netzwerkadressen zu gewährleisten. 1.2.4 Ports Den einzelnen Prozessen werden bei beiden Sockettypen Ports zugeordnet, dies sind IntegerZahlen im Bereich 0...65535. Da die beiden Sockets in unterschiedlichen Namensräumen liegen, kann eine Port-Nummer gleichzeitig für TCP- und UDP Sockets verwendet werden. 3 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Das nachfolgende Schaubild soll noch einmal anhand verschiedener Prozesse die Einordnung der einzelnen Sockettypen in den Gesamtprozess verdeutlichen: (Quelle: Microsoft Technischer Support) 1.2.5 Ablauf eines Kommunikationsprozesses über Sockets Um eine Socketverbindung aufzubauen und zu nutzen, muss zuerst ein Socket-Server eingerichtet werden. Das läuft in zwei Schritten ab. 1. Erst wird der Socket erstellt und anschließend wird ihm eine Portnummer zugewiesen, auf der er auf eingehende Verbindungen wartet. Danach unterscheidet sich der Ablauf abhängig davon, ob ein Streamsocket oder ein Datagrammsocket eingesetzt wird. 4 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann 2.a) Bei einem Stream-Socket meldet sich ein Client an und teilt dem Server dabei seine IP Adresse und die Portnummer mit. Dann besteht eine dauerhafte Verbindung und es können Daten in beliebig vielen Lese- und Schreibzyklen ausgetauscht werden. Anschließend wird die Verbindung beendet. Dabei ist sichergestellt, dass alle Pakte eintreffen, da die Pakete durchnummeriert sind. Fehlt also ein Paket, stellt der Server oder der Client das Überspringen einer Nummer fest und kann darauf reagieren. 5 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann 2.b) Bei einem Datagrammsocket findet keine Anmeldung statt.Der Client schickt ohne Anmeldung sofort die zu übertragenden Daten. Durch diese Pakete bekommt der Server die IP Adresse und die Portnummer mitgeteilt und kann gegebenenfalls dem Client antworten. Eine Verbindung muss nicht beendet werden, da jedes Paket selbstständig und ohne Kontrolle übertragen wird. Dadurch gehen allerdings leicht Daten verloren, da weder Server noch Client feststellen können ob der jeweils andere die Pakete erhalten hat. Der Clientsocket muss ebenfalls zuerst erstellt werden. Dann muss ihm die IP Adresse und die Portnummer des Servers mitgeteilt werden, damit er sich dort anmelden (Streamsocket) bzw. direkt mit ihm kommunizieren kann (Datagrammsocket). Sind alle Daten ausgetauscht beendet der Client die Verbindung und kann wieder aus dem Speicher entfernt werden. 1.2.6 Sockets im Betriebssystem Windows Die folgende Grafik verdeutlicht die Position dieses Windows-Sockets im Schichtenmodell: Anwendungen können direkt auf den Windows-Socket (WinSock-API) aufsetzen, oder Komponenten verwenden, die ihrerseits die Funktionalität des WinSock-APIs verwenden. Die Programmierumgebung von Delphi stellt mit der Datei WinSock.pas bzw. WinSock.dcu ein an Object-Pascal angepasstes zwischengeschaltetes API zur Verfügung. 6 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann In Delphi stehen ferner fertige Komponenten zur Verfügung (TServerSocket, TClientSocket), die die Verwendung der WinSock-Funktionalität in Form eines Steuerelement (Controls, Komponente der VCL) kapseln. (Quelle: Lars Gollub, Messen, Steuern und Regeln mit TCP/IP, Franzis' Verlag, Poing 2003) 1.2.7 Socket-Komponenten in Delphi Vor Beginn der Socket-Programmierung müssen Sie sicherstellen, dass Ihr Programmiersystem die Socket-Komponenten TServerSocket und TClientSocket zur Verfügung stellt. Die Komponente TServerSocket Die Komponente TClientSocket Dieses erste Programmbeispiel beschreibt die grundlegenden Techniken der SocketProgrammierung unter Verwendung der beiden Delphi-Klassen TServerSocket und TClientSocket. Das Programm verwendet als IP Adresse die symbolische Adresse 'Localhost' (= 127.0.0.1) und den Port 8181 für den Serversocket. Port = 8181 Der Port ist hier mit 8181 voreingestellt. 7 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Host = Localhost oder Host = 127.0.0.1 Als IP Adresse verwendet eine Serversocket-Komponente die des aktuellen Rechners. Eigenschaft Socket Socket-Komponenten besitzen die Eigenschaft Socket. Diese existiert nur zur Laufzeit des Programms und wird daher nicht im Objektinspektor angezeigt. Die Eigenschaft Socket kapselt Socket-Objekte, die die Funktionalität eines Sockets aus dem WinSock-API bereitstellen. Daher sind unter dieser Eigenschaft weitere Eigenschaften und Methoden vorhanden, insbesondere die zum Start eines Sockets. mittels Methode: ServerSocket.Open ServerSocket.Close oder mittels Eigenschaft: ServerSocket.Active := True ServerSocket.Active := False Wichtige Ereignisse der Client-Socket-Komponente Ereignis Das Ereignis tritt ein OnConnect unmittelbar vor dem Öffnen der Verbindung zu Serversocket OnRead wenn ein Clientsocket Informationen aus der Socketverbindung lesen soll OnWrite wenn ein Clientsocket Informationen in die Socketverbindung schreiben soll OnDisconnect vor dem Schließen der Verbindung zu einem Servesocket OnError wenn ein Socket eine Verbindung nicht erstellen, verwenden oder schließen kann Wichtige Ereignisse der Serversocket-Komponente Ereignis Das Ereignis tritt ein OnAccept unmittelbar nach dem Akzeptieren der Verbindung mit einem Clientsocket OnClientConnect wenn ein Clientsocket eine vom Serversocket akzeptierte Verbindung einrichtet OnClientRead wenn der Serversocket Informationen aus dem Clientsocket lesen muss OnClientWrite wenn der Serversocket Informationen in einen Clientsocket 8 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann schreiben muss OnClientDisconnect wenn eine der Verbindungen zu einem Clientsocket geschlossen wird OnClientError wenn beim Einrichten, Verwenden oder Beenden der Socketverbindung zu einem Clientsocket ein Fehler auftritt Um in einem nächsten Schritt den Kontakt zwischen zwei Rechnern herzustellen, müssen dem Client-Socket lediglich die IP-Adresse und der Port des Servers mitgegeben werden. 1.2.8 Datenaustausch über Sockets Auch der Datenaustausch zwischen den Socket-Komponenten erfolgt ereignisgesteuert. Schließlich kann ein Socket ja nicht im Voraus 'wissen', wann ein anderer Socket über ihn Daten austauschen möchte. Ist die Verbindung zwischen Sockets hergestellt, treten nun in unregelmäßigen Abständen weitere Ereignisse auf, insbesondere: für die Clientsocket-Komponente Ereignis Das Ereignis tritt ein OnRead wenn ein Clientsocket Informationen aus der Socketverbindung lesen kann. für die Serversocket-Komponente Ereignis Das Ereignis tritt ein OnClientRead wenn der Serversocket Informationen aus dem Clientsocket lesen kann. Die Socket-Komponenten reagieren auf diese Ereignisse, indem Sie über die bestehende Socketverbindung mithilfe der Eigenschaft Socket Daten senden oder empfangen. Eigenschaft Beschreibung Connected gibt an, ob die Socketverbindung geöffnet ist und für die Kommunikation zur Verfügung steht. x LocalAdress legt die IP Adresse des lokalen Systems fest, das mit der Socketverbindung verbunden ist x LocalHost gibt den Namen des lokalen Systems an x LocalPort gibt die ID Nummer des von dem Socket verwendeten Ports an 9 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann x RemoteAdress gibt die IP Adresse des Remote-Systems in der Socketverbindung an x RemodeHost gibt den Namen des entfernten Systems an x RemotePort gibt die ID Nummer des vom entfernten System (RemoteHost) für die Socketverbindung verwendeten Ports an. Methoden der Property Socket (Auszug) function SendText (const S: string): Integer; Schreibt eine Zeichenkette (String) in die Socketverbindung. function ReceiveText: string; Liest eine Zeichenkette (String) aus der Socketverbindung. function SendBuf (var Buf; Count: Integer): Integer; Schreibt einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') in die Socketverbindung. Bei der Datenübertragung ist immer die Länge Count der Daten (= Anzahl Bytes) anzugeben, damit der Empfänger weiß wie groß die Datenmenge ist. function ReceiveBuf (var Buf; Count: Integer): Integer; Liest einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') der Länge Count (Bytes) aus der Socketverbindung. Die Funktionen SendText, ReceiveText, SendBuf und ReceiveBuf können 'Turbo-Pascaltypisch" auch prozedural verwendet werden. Als Funktion liefern sie über ihren Funktionswert die Anzahl der tatsächlich übertragenen Bytes oder den Wert -1, falls keine Übertragung stattfand. Detailliertere Informationen zur Eigenschaft Socket finden sich in der Hilfedatei von Delphi sowie in der Beschreibung der Klassen TServerSocket und TClientSocket (hier an anderer Stelle). 10 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann 2. Die Komponente TClientSocket Das Objekt TClientSocket verwaltet die Socket-Verbindungen für einen TCP/IP Client. TClientSocket definiert die gewünschte Verbindung zu einem TCP/IP Server, verwaltet die Verbindung in geöffnetem Zustand und beendet sie bei Bedarf. Die Klasse TClientSocket ist zu Programmierung von Anwendungen und Diensten, die auf das UDP Protokoll aufsetzen, nicht geeignet. Kurzbeschreibung Mithilfe der Socket-Komponenten lassen sich Sockets, die in diesen Komponenten gekapselt sind, Delphi-typisch verwenden. Socket-Komponenten finden sich in der Komponentenbibliothek (VCL) und können zur Entwicklungszeit des Programms in das verwaltende Fenster gezogen werden. Socket-Komponenten werden wie alle anderen Komponenten in der Komponentenliste des Formulars verwaltet. Socket-Komponenten kapseln ihre Sockets durch Eigenschaften und Ereignisse. Grundlegende Eigenschaften können bereits zur Entwurfszeit im Objektinspektor initialisiert werden, die grundlegende Eigenschaft Socket kapselt einen Socket zur Laufzeit des Programms. Die Kontaktaufnahme zwischen Sockets ist ebenso wie ihre Kommunikation ereignisgesteuert. Benutzerschnittstelle der Klasse TClientSocket Methoden constructor Create (AOwner: TComponent); Die Konstruktor Create erzeugt ein Exemplar von TClientSocket zur Laufzeit. TClientSocket-Objekte, die während des Entwurfs in einem Formular platziert wurden, werden automatisch erzeugt. destructor Destroy; Der Destruktor Destroy gibt ein Exemplar von TClientSocket wieder frei. Die Methode Free verwendet ebenfalls diesen Destruktor. Free überprüft, ob der ClientSocket nicht bereits nil ist und ruft Destroy nur bei Bedarf auf. procedure Open; Die Methode Open öffnet die Socket-Verbindung und initialisiert sie. Die Eigenschaft Active wird dabei auf True gesetzt. Der Client-Socket sucht dann nach einem Server und übernimmt den Verbindungsaufbau. 11 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann procedure Close; Die Methode Close schließt die Socket-Verbindung. Rufen Sie Close auf, um die Socket-Verbindung zu schließen. Close setzt die Eigenschaft Active auf False. Eigenschaften im Objektinspektor Eigenschaft x Active Address Typ Beschreibung Boolean gibt an, ob die Socket-Verbindung geöffnet und für die Kommunikation mit anderen Systemen verfügbar ist. string bezeichnet die IP Adresse des Server-Systems. Address ist ein String aus vier numerischen (Byte-) Werten, die durch Punkte voneinander getrennt werden. Beispiel: 123.197.1.2 . Wenn der Socket die Eigenschaft Host definiert, wird die Adresse für die Verbindung nicht aus der Eigenschaft Address, sondern aus der IP Adresse übernommen, die mit Host gekoppelt ist. Diese zweite Variante ist schneller, da der Socket nicht erst nach der IP-Adresse suchen muss. legt fest, ob der Client-Windows-Socket Informationen über die Socketverbindung asynchron liest und schreibt. ClientType ist ein Alias für die IP Adresse des Server-Systems. Wenn der Socket eine Verbindung öffnet, sucht er mit Hilfe des Wertes von Host nach der IP Adresse für den Serversocket. x Host x Name string gibt den Namen der Komponente im Formular an. x Port Integer enthält die ID, die zur Bezeichnung der ServerSocketverbindung benutzt wird. Client und Server benötigen für eine Verbindung den selben Port. Standarddiensten, z.B. Chat, E-Mail etc. , sind feste Port-Nummern zugeordnet. Service string bezeichnet den Namen des Dienstes, für den die Socketverbindung eingesetzt wird. Verwenden Sie Service, um auf den Verwendungszweck der Verbindung hinzuweisen. Windows stellt eine Anzahl von Namen für Standard-Dienste bereit, z.B. ftp, http, finger und time. Tag Integer speichert eine Ganzzahl als Teil der Komponente. Diese Zahl wird intern nicht verwendet und bietet dem Programmentwickler eine Speicherstelle zur freien Verfügung. 12 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Eigenschaften zur Laufzeit Eigenschaft x Socket Beschreibung Mithilfe der Eigenschaft (Property) Socket wird eine ClientSocketverbindung zur Laufzeit des Programms verwaltet. Durch diese Eigenschaft wird ein Objekt der Klasse TClientWinSocket verfügbar, das die Funktionalität eines Clientsockets kapselt, und wiederum Eigenschaften und Methoden besitzt. x = wichtige Eigenschaft in diesem Zusammenhang Socket: Gemeinsame Eigenschaften von TServerWinSocket und von TClientWinSocket Eigenschaft Typ Beschreibung x Connected Boolean gibt an, ob die Socketverbindung geöffnet ist und für die Kommunikation zur Verfügung steht. x LocalAdress string gibt die IP Adresse des Systems an. x LocalHost string enthält den Namen des Systems, in dem die Anwendung ausgeführt wird, die den WindowsSocket verwendet. x LocalPort Integer gibt die ID Nummer des von dem Socket verwendeten Ports an gibt an, ob während des Öffnens der Verbindung asynchrone Aktivitäten auftreten. LookupState x RemoteAdress string legt die IP Adresse des lokalen Systems fest, das mit der Socketverbindung verbunden ist x RemodeHost string enthält den Namen des Systems am anderen Ende der Socketverbindung. x RemodePort Integer gibt die ID Nummer des vom entfernten System (RemoteHost) für die Socketverbindung verwendeten Ports an. SocketHandle gibt das Windows-Handle für den Socket an. x = wichtige Eigenschaft in diesem Zusammenhang Socket: Spezielle Eigenschaften von TClientWinSocket Eigenschaft Beschreibung ClientType legt fest, ob der Client-Windows-Socket Informationen über die Socket-Verbindung asynchron liest und schreibt. x = wichtige Eigenschaft in diesem Zusammenhang 13 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Socket: Methoden von TClientWinSocket (Auszug) function SendText (const S: string): Integer; Schreibt eine Zeichenkette (String) in die Socketverbindung. function ReceiveText: string; Liest eine Zeichenkette (String) aus der Socketverbindung. function SendBuf (var Buf; Count: Integer): Integer; Schreibt einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') in die Socketverbindung. Bei der Datenübertragung ist immer die Länge Count der Daten (= Anzahl Bytes) anzugeben, damit der Empfänger weiß wie groß die Datenmenge ist. function ReceiveBuf (var Buf; Count: Integer): Integer; Liest einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') der Länge Count (Bytes) aus der Socketverbindung. Einige Hinweise zur Verwendung dieser Methoden: Die übertragenen Daten werden in den Sockets zwischengepuffert. Wird mit ReceiveText bzw. ReceiveBuf ein Datensatz gelesen, wird er anschließend aus diesem Puffer entfernt. Ein weiteres Lesen dieser Informationen aus dem Socket ist nicht möglich. Mithilfe der Systemfunktion function SizeOf (X): Integer kann der für einen untypisierten Datenbereich X benötigte Speicherplatz (= Anzahl Bytes) ermittelt werden. Beispiel: SendText ('Hallo') ist also identisch mit SendBuf ('Hallo', SizeOf ('Hallo')). Die Verwendung von SendBuf und ReceiveBuf setzt voraus, dass diese benötigte Speicherplatz konstant ist und vorher berechnet werden kann. Sogenannte 'Nullterminierte Strings' (String-Format für Programmiersprache C und Abkömmlinge) haben eine unbestimmte Länge. Verwenden Sie möglichst 'Pascal-Strings'. Beispiel: var Zeichenfolge: string [255]. Die Funktions-Methoden können 'Turbo-Pascal-typisch" auch prozedural verwendet werden. Als Funktion liefern sie über ihren Funktionswert die Anzahl der tatsächlich übertragenen Bytes oder den Wert -1, falls keine Übertragung stattfand. 14 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Ereignisse Die Kommunikation zwischen den Socket-Komponenten erfolgt ereignisgesteuert. Schließlich kann ein Socket ja nicht im Voraus 'wissen', wann ein anderer Socket eine Verbindung aufbauen oder Daten austauschen möchte. Ereignisse für den Verbindungsaufbau und Verbindungsabbau: property OnLookup Das Ereignis OnLookup tritt ein , wenn ein Clientsocket nach dem Serversocket sucht, zu dem die Verbindung hergestellt werden soll. property OnConnect Das Ereignis OnConnect tritt für Clientsockets ein, wenn die Verbindung zum Server geöffnet wurde. In einer Behandlungsroutine für das Ereignis OnConnect eines Clientsocket können Sie Aktionen festlegen, die nach dem Aufbau der Verbindung zu einem Serversocket ausgeführt werden. property OnConnecting Das Ereignis OnConnecting tritt für einen Clientsocket ein, nachdem der Serversocket lokalisiert wurde, aber bevor die Verbindung aufgebaut wird. In einer Behandlungsroutine für das Ereignis OnConnecting eines Clientsocket können Sie Aktionen festlegen, die direkt vor dem Aufbau der Verbindung zu einem Serversocket ausgeführt werden. property OnConnect Das Ereignis OnConnect tritt für einen Clientsocket ein, wenn die Verbindung zum Server geöffnet wurde. In einer Behandlungsroutine für das Ereignis OnConnect eines Clientsocket können Sie Aktionen festlegen, die nach dem Aufbau der Verbindung zu einem Serversocket ausgeführt werden. property OnDisconnect Das Ereignis OnDisconnect tritt direkt vor dem Schließen der Verbindung zu einem Serversocket durch den Clientsocket ein. In einer Behandlungsroutine für das Ereignis OnDisconnect können Sie Aktionen festlegen, die ausgeführt werden, kurz bevor die Verbindung zu einem Serversocket beendet wird. OnDisconnect tritt ein, nachdem die Eigenschaft Active auf False gesetzt wurde, aber bevor die Verbindung tatsächlich geschlossen wird. Ereignisse für die Kommunikation: property OnRead 15 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Das Ereignis OnRead tritt ein, wenn ein Clientsocket Informationen aus der SocketVerbindung lesen soll. Schreiben Sie eine Behandlungsroutine für das Ereignis OnRead, um aus der Socket-Verbindung zu lesen. property OnWrite Das Ereignis OnWrite tritt ein, wenn ein Clientsocket Informationen in die Socketverbindung schreiben soll. Schreiben Sie eine Behandlungsroutine für das Ereignis OnWrite, um in die Socketverbindung zu schreiben. Ereignisse für die Fehlerbehandlung: property OnError Das Ereignis OnError tritt ein, wenn der Socket eine Verbindung nicht herstellen, benutzen oder schließen kann. In einer Behandlungsroutine für OnError können Sie auf Fehler reagieren, die in Zusammenhang mit einer Socketverbindung auftreten. Wenn die Ereignisbehandlungsroutine für OnError die Fehlerbedingung erfolgreich behandeln konnte, setzen Sie den Parameter ErrorCode auf 0, damit keine ESocketError-Exception ausgelöst wird. Einige Hinweise zur inneren Struktur der Komponente TClientSocket Die Klasse TClientSocket ist als Delphi-Komponente eine Unterklasse von TComponent. Socket-Komponenten besitzen also alle Merkmale von Komponenten, z. B. die Eigenschaft Name, aber auch eine Komponentenliste (Eigenschaft Components) zur Verwaltung weiterer, untergeordneter Komponenten. 16 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann (Abb. Klassenhiearchie der Socket-Komponenten) Aktive Client-Socket-Objekte stellen ein Socket-Objekt für die Verbindungsaufnahme des Clients mit einem Server zur Verfügung. Die gesamte Verwaltung dieser Sockets übernimmt ein Objekt der Klasse TClientWinSocket. Die Kommunikation zwischen Verwaltungsobjekt und Komponente übernimmt die Eigenschaft Socket. (Abb. WinSocket-Klassen kapseln Sockets) Der Verbindungs-Socket wird in dem internen Attribut FSocket: TClientWinSocket verwaltet, für die "Kommunikatons-Sockets" existiert das Attribut FConnections: TList, das über die Eigenschaft Connections administriert wird. 17 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Sowohl die Komponente TClientSocket als auch die Klasse TClientWinSocket sind also Endpunkte eine Hierarchie von Klassen. Die Definition der hier beschriebenen Benutzerschnittstellen und Zusammenhänge verteilt sich auf diese verschiedenen Oberklassen. 3. Die Komponente TServerSocket Das Objekt TServerSocket verwaltet die Socketvrbindungen für einen TCP/IP Server. Ein aktives TServerSocket-Objekt stellt einen Socket zur Verfügung, an dem sich Clientsockets anmelden können, und erzeugt für jeden angemeldeten Client zusätzlich einen weiteren Socket für die Kommunikation. Die Klasse TServerSocket ist zu Programmierung von Anwendungen und Diensten, die auf dem UDP Protokoll aufsetzen, nicht geeignet. Kurzbeschreibung Mithilfe der Socket-Komponenten lassen sich Socket, die in diesen Komponenten gekapselt sind, Delphi-typisch verwenden. Socket-Komponenten finden sich in der Komponentenbibliothek (VCL) und können zur Entwicklungszeit des Programms in das verwaltende Fenster gezogen werden. Socket-Komponenten werden wie alle anderen Komponenten in der Komponentenliste des Formulars verwaltet. Socket-Komponenten kapseln ihre Sockets durch Eigenschaften und Ereignisse. Grundlegende Eigenschaften können bereits zur Entwurfszeit im Objektinspektor initialisiert werden, die grundlegende Eigenschaft Socket kapselt einen Socket zur Laufzeit des Programms. Die Kontaktaufnahme zwischen Sockets ist ebenso wie ihre Kommunikation ereignisgesteuert. Benutzerschnittstelle der Klasse TServerSocket Methoden 18 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann constructor Create (AOwner: TComponent); Die Konstruktor Create erzeugt ein Exemplar von TServerSocket zur Laufzeit. ServerSocket-Objekte, die während des Entwurfs in einem Formular platziert wurden, werden automatisch erzeugt. destructor Destroy; Der Destruktor Destroy gibt ein Exemplar von TServerSocket wieder frei. Die Methode Free verwendet ebenfalls diesen Destruktor. Free überprüft, ob der Serversocket nicht bereits nil ist, und ruft Destroy nur bei Bedarf auf. procedure Open; Die Methode Open öffnet die Socketverbindung und initialisiert sie. Hierzu wird ein Port benötigt den man der Eigenschaft Port zuweisen muss. Als IP Adresse wird die IP Adresse des Computers genutzt, auf dem das Programm ausgeführt wird. Die Eigenschaft Active wird auf True gesetzt. Der Serversocket steht dann für den Verbindungsaufbau mit einem Clientsocket zur Verfügung. procedure Close; Die Methode Close schließt die Socketverbindung. Rufen Sie Close auf, um die Socketverbindung zu schließen. Close setzt die Eigenschaft Active auf False. Eigenschaften im Objektinspektor Eigenschaft Typ Beschreibung x Active Boolean gibt an, ob die Socketverbindung geöffnet und für die Kommunikation mit anderen Systemen verfügbar ist. x Name string gibt den Namen der Komponente im Formular an. x Port Integer enthält die ID, die zur Bezeichnung der ServerSocketverbindung benutzt wird. Client und Server benötigen für eine Verbindung denselben Port. bestimmt, ob alle vom Serversocket akzeptierten Verbindungen nicht blockierend sind oder ob automatisch ein separater Thread angegeben wird. ServerType Service string bezeichnet den Namen des Dienstes, für den die Socketverbindung eingesetzt wird. Verwenden Sie Service, um auf den Verwendungszweck der Verbindung hinzuweisen. Windows stellt eine Anzahl von Namen für Standard-Dienste bereit, z.B. ftp, http, finger und time. Server können in 19 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann einer SERVICES-Datei zusätzliche Dienste und zugehörige Schnittstellen (Eigenschaft Port) angeben. Integer speichert eine Ganzzahl als Teil der Komponente. Diese Zahl wird intern nicht verwendet und bietet dem Programmentwickler eine Speicherstelle zur freien Verfügung. ThreadCacheSize Integer gibt die maximale Anzahl der Threads an, die für neue Client-Verbindungen wieder verwendet werden können. Tag x = wichtige Eigenschaft in diesem Zusammenhang Eigenschaften zur Laufzeit Eigenschaft x Socket Beschreibung Mithilfe der Eigenschaft (Property) Socket wird eine ServerSocketverbindung zur Laufzeit des Programms verwaltet. Durch diese Eigenschaft wird ein Objekt der Klasse TServerWinSocket verfügbar, das die Funktionalität eines Serversockets kapselt, und wiederum Eigenschaften und Methoden besitzt. Socket: Gemeinsame Eigenschaften von TServerWinSocket und von TClientWinSocket Eigenschaft Typ Beschreibung x Connected Boolean gibt an, ob die Socketverbindung geöffnet ist und für die Kommunikation zur Verfügung steht. x LocalAdress string gibt die IP Adresse des Systems an. x LocalHost string enthält den Namen des Systems, in dem die Anwendung ausgeführt wird, die den WindowsSocket verwendet. x LocalPort Integer gibt die ID Nummer des von dem Socket verwendeten Ports an gibt an, ob während des Öffnens der Verbindung asynchrone Aktivitäten auftreten. LookupState x RemoteAdress string legt die IP Adresse des lokalen Systems fest, das mit der Socketverbindung verbunden ist x RemodeHost string enthält den Namen des Systems am anderen Ende der Socketverbindung. x RemodePort Integer gibt die ID Nummer des vom entfernten System 20 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann (RemoteHost) für die Socketvrbindung verwendeten Ports an. gibt das Windows-Handle für den Socket an. SocketHandle x = wichtige Eigenschaft in diesem Zusammenhang Im Gegensatz zur Eigenschaft Socket eines Clientsockets, die ein TClientWinSocket-Objekt kapselt, verwaltet ein TServerWinSocket-Objekt alle Informationen über die aktuell auf dem Serversocket aktiven Verbindungen. Socket: Spezielle Eigenschaften von TServerWinSocket Eigenschaft Typ Beschreibung ActiveConnections Integer gibt die Anzahl der geöffneten Verbindungen zu Clientsockets an. x ActiveThreads x Integer gibt die Anzahl der TServerClientThreadObjekte an, die aktuell von dem in der Feldstruktur Connections aufgeführten Socketvrbindungen verwendet werden führt alle geöffneten Socketverbindungen zu Clientsckets auf. Connections IdleThreads Integer gibt die Anzahl der nicht verwendeten TServerClientThread-Objekte an, die sich im Zwischenspeicher befinden. ServerType bestimmt, ob alle vom Serversocket akzeptierten Verbindungen nichtblockierend sind oder ob automatisch ein separater Thread angegeben wird. x = wichtige Eigenschaft in diesem Zusammenhang Socket: Methoden von TClientWinSocket (Auszug) function SendText (const S: string): Integer; Schreibt eine Zeichenkette (String) in die Socketverbindung. function ReceiveText: string; Liest eine Zeichenkette (String) aus der Socketverbindung. function SendBuf (var Buf; Count: Integer): Integer; Schreibt einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') in die Socketverbindung. Bei der Datenübertragung ist immer die Länge Count der Daten (= Anzahl Bytes) anzugeben, damit der Empfänger weiß wie groß 21 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann die Datenmenge ist. function ReceiveBuf (var Buf; Count: Integer): Integer; Liest einen beliebigen, unstrukturierten, nicht typisierten Datenbereich Buf (= 'Buffer') der Länge Count (Bytes) aus der Socketverbindung. Einige Hinweise zur Verwendung dieser Methoden: Die übertragenen Daten werden in den Sockets zwischengepuffert. Wird mit ReceiveText bzw. ReceiveBuf ein Datensatz gelesen, wird er anschließend aus diesem Puffer entfernt. Ein weiteres Lesen dieser Informationen aus dem Socket ist nicht möglich. Mithilfe der Systemfunktion function SizeOf (X): Integer kann der für einen untypisierten Datenbereich X benötigte Speicherplatz (= Anzahl Bytes) ermittelt werden. Beispiel: SendText ('Hallo') ist also identisch mit SendBuf ('Hallo', SizeOf ('Hallo')). Die Verwendung von SendBuf und ReceiveBuf setzt voraus, dass diese benötigte Speicherplatz konstant ist und vorher berechnet werden kann. Sogenannte 'Nullterminierte Strings' (String-Format für Programmiersprache C und Abkömmlinge) haben eine unbestimmte Länge. Verwenden Sie möglichst 'Pascal-Strings'. Beispiel: var Zeichenfolge: string [255]. Die Funktions-Methoden können 'Turbo-Pascal-typisch" auch prozedural verwendet werden. Als Funktion liefern sie über ihren Funktionswert die Anzahl der tatsächlich übertragenen Bytes oder den Wert -1, falls keine Übertragung stattfand. Ereignisse Die Kommunikation zwischen den Socket-Komponenten erfolgt ereignisgesteuert. Schließlich kann ein Socket ja nicht im Voraus 'wissen', wann ein anderer Socket eine Verbindung aufbauen oder Daten austauschen möchte. Ereignisse für den Verbindungsaufbau und Verbindungsabbau: property OnAccept unmittelbar nach dem Akzeptieren der Verbindung mit einem Clientsocket property OnClientConnect wenn ein Clientsocket eine vom Serversocket akzeptierte Verbindung einrichtet property OnClientDisconnect 22 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann wenn eine der Verbindungen zu einem Clientsocket geschlossen wird Ereignisse für die Kommunikation: property OnClientRead Das Ereignis OnClientRead tritt ein, wenn ein Serversocket Informationen aus der Socketverbindung lesen soll. Schreiben Sie eine Behandlungsroutine für das Ereignis OnClientRead, um aus der Socketverbindung zu lesen. property OnClientWrite Das Ereignis OnWrite tritt ein, wenn ein Serversocket Informationen in die Socketverbindung schreiben soll. Schreiben Sie eine Behandlungsroutine für das Ereignis OnWrite, um in die Socketverbindung zu schreiben. Ereignisse für die Fehlerbehandlung: property OnClientError Das Ereignis OnClientError tritt ein, wenn beim Einrichten, Verwenden oder Beenden der Socketverbindung zu einem Clientsocket ein Fehler auftritt. In einer Behandlungsroutine für OnClientError können Sie auf Fehler reagieren, die in Zusammenhang mit einer Socketverbindung auftreten. Wenn die Ereignisbehandlungsroutine für OnClientError die Fehlerbedingung erfolgreich behandeln konnte, setzen Sie den Parameter ErrorCode auf 0, damit keine ESocketError-Exception ausgelöst wird. Sonstige Ereignisse (in diesem Zusammenhang unwichtig): property OnGetSocket Das Ereignis OnGetSocket tritt ein, wenn der Serversocket ein neues TServerClientWinSocket-Objekt erstellen muss, das den Server-Endpunkt einer Verbindung zu einem Clientsocket repräsentiert. property OnGetThread Das Ereignis OnGetThread tritt ein, wenn der Serversocket einen neuen Thread für eine Verbindung zu einem Clientsocket erzeugen muss. property OnThreadStart Das Ereignis OnThreadStart tritt ein, wenn der Thread für eine Verbindung zu einem Clientsocket gestartet wird. property OnThreadEnd 23 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann Das Ereignis OnThreadEnd tritt ein, wenn eine Client-Socketverbindung und der damit verbundene Thread beendet werden. Einige Hinweise zur inneren Struktur der Komponente TServerSocket Die Klasse TServerSocket ist als Delphi-Komponente eine Unterklasse von TComponent. Socket-Komponenten besitzen also alle Merkmale von Komponenten, z. B. die Eigenschaft Name, aber auch eine Komponentenliste (Eigenschaft Components) zur Verwaltung weiterer, untergeordneter Komponenten, auch wenn diese für die Verwaltung der Sockets nicht benutzt wird. (Abb. Klassenhiearchie der Socket-Komponenten) Aktive Serversocket-Objekte stellen ein Socket-Objekt für die Verbindungsaufnahme eines Clients mit dem Server zur Verfügung, zusätzlich für jede erfolgreiche Kontaktaufnahme einen weiteren Socket für die Kommunikation mit dem Clientsocket. Die gesamte Verwaltung dieser Sockets übernimmt ein Objekt der Klasse TServerWinSocket. Die Kommunikation zwischen Verwaltungsobjekt und Komponente übernimmt die Eigenschaft Socket. 24 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann (Abb. WinSocket-Klassen kapseln Sockets) Der Verbindungssocket wird in dem internen Attribut FServerSocket: TServerWinSocket verwaltet, für die "Kommunikatons-Sockets" existiert das Attribut FConnections: TList, das über die Eigenschaft Connections administriert wird. (Abb. Server-Socket: Verwaltung verbundener Client-Sockets) Sowohl die Komponente TServerSocket als auch die Klasse TServerWinSocket sind also Endpunkte eine Hierarchie von Klassen. Die Definition der hier beschriebenen Benutzerschnittstellen und Zusammenhänge verteilt sich auf die einzelnen Oberklassen. 25 Skript Informatik Grundkurs G8, © by Thorsten Frey & Dirk Bermann 26