![]() |
Dieses erste Programmbeispiel beschreibt die grundlegenden Techniken der Socket-Programmierung unter Verwendung der beiden Delphi-Klassen TServerSocket und TClientSocket.
Client-Server-Anwendungen verwenden in der Regel unterschiedliche Rechner für das Server- und das Client-Programm. Für diesen ersten Zugriff (Programm Kontakt1) verwendet das Programm zugleich einen Serversocket und einen Clientsocket, repräsentiert durch zwei verschiedene Fenster. Man kann damit beide Aspekte der Client-Server Kommunikation in einem Programm erfahren und ausprobieren.Das Programm verwendet als IP Adresse die symbolische Adresse 'Localhost'
(= 127.0.0.1) und den Port 8181 für den Serversocket.

Das Programm Kontakt1 beschreibt und demonstriert die grundlegenden Techniken der Kontaktaufnahme von einem Client mit einem Server und die Kommunikation dieser beiden Sockets. Das Programm enthält neben dem Hauptfenster hierzu zwei weitere Fenster, die als Server- und als Client-Prozess arbeiten. Demzufolge besitzen diese Fenster jeweils eine Serversocket- bzw. eine Clientsocket-Komponente, dazu weitere Steuerelemente.
Sprechweise: Wir sprechen im Weiteren etwas unpräzise, aber
vereinfachend von einem Server (bzw. Client), und identifizieren den
Server-Rechner mit dem Server-Programm und mit seinem Serversocket.
Das Server-Fenster
Das Server-Programm enthält eine Schaltfläche um den Serversocket
zu
starten oder zu stoppen., ferner ein Memo-Feld, um den Status der
Kommunikation anzuzeigen, und natürlich eine Serversocket-Komponente.

Die Namen der Komponenten:
| Name |
Komponente |
| FrmServer | Formular |
| ServerSocket | Serversocket-Komponente |
| BtStartStop | Schaltfläche |
| MemStatus | Memo-Feld |
| Port = 8181 | Der Port ist hier mit 8181 voreingestellt. |
| 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.
Öffnen und Schließen eines Sockets
| mittels Methode: |
ServerSocket.Open ServerSocket.Close |
| oder mittels Eigenschaft: |
ServerSocket.Active := True ServerSocket.Active := False |
Die Ereignismethode der Schaltfläche BtStartStop, die den Server öffnet oder schließt, demonstriert die Verwendung der oben beschriebenen Eigenschaften und Methoden.
| procedure
TFrmServer.BtStartStopClick (Sender: TObject); begin if ServerSocket.Active then begin ServerSocket.Active := False; // ServerSocket.Close; BtStartStop.Caption := 'Server Start'; MemStatus.Lines.Add ('Status: Server angehalten') end else begin ServerSocket.Active := True; // ServerSocket.Open; ServerAktiv := True; BtStartStop.Caption := 'Server Stop'; MemStatus.Lines.Add ('Status: Server gestartet') end end; |
Server aktiv? ja: Server anhalten geht auch nein: Server starten geht auch |
Das Client-Fenster
Das Client-Fenster hat die gleiche Struktur wie das Server-Fenster: Mithilfe der Schaltfläche BtVerbinden kann sich der Client mit dem Serversocket verbinden und diese Verbindung wieder trennen. Der Status des Clients wird im Memo-Feld protokolliert.

Die Fensterkomponente verwendet das Attribut Verbunden: Boolean
für die interne Verwaltung des Zustandes der Verbindung.
Die Namen der verwendeten Komponenten:
| Name | Komponente |
| FrmClient | Formular |
| Verbunden: Boolean; | (interne) Zustandsvariable |
| ClientSocket | Clientsocket-Komponente |
| BtVerbinden | Schaltfläche |
| MemStatus | Memo-Feld |
| procedure
TFrmClient.BtVerbindenClick(Sender: TObject); begin if Verbunden then begin ClientSocket.Close; Verbunden := False; BtVerbinden.Caption := 'Mit Server verbinden'; end else begin ClientSocket.Host := Adresse; ClientSocket.Port := Port; ClientSocket.Open; Verbunden := True; BtVerbinden.Caption := 'Vom Server trennen'; end end; |
Mit Server verbunden? ja: Verbindung trennen nein: Verbindung herstellen |
Fehlermeldungen
Lässt sich eine der oben beschriebenen Socket-Operationen nicht ausführen, tritt also ein Verbindungsfehler auf, so wird für die betroffene Socket-Komponente das Ereignis OnError ausgelöst und das Programm mit einem entsprechenden Error-Code unterbrochen.
Typisches Beispiel: Der Client versucht sich mit dem nicht geöffneten Server zu verbinden (Fehlermeldung 100061)

Man kann diese Programmunterbrechung unterbinden, indem man diese
Fehlermeldungen in der zum Ereignis OnError gehörenden
Ereignismethode bearbeitet und abschließend den Error-Code auf 0
zurücksetzt. Da diese Ereignismethode vor der Error-Behandlung
des Delphi-Systems bearbeitet wird, wird hierdurch ein solcher
Programmabbruch verhindert.
| procedure
TFrmClient.ClientSocketError (Sender: TObject; Socket:
TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin MemStatus.Lines.Add ('Status: Fehler ' + IntToStr(ErrorCode)); ... ErrorCode := 0; end; |
Eventuell weitere Reaktionen auf den Fehler Verhindert eine Fehlermeldung des Systems |
Weitere Ereignisse
Auch während der einzelnen Aktionen zwischen Client und Server
(Verbinden, Trennen, Datenaustausch) werden Delphi-typisch zahlreiche
Ereignisse ausgelöst.
Wichtige Ereignisse des 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 des 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 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 |
Beispiel
Bei der Aktivierung eines Clientsockets werden die den Ereignisse
zugeordneten Ereignis-Methoden in dieser Abfolge ausgeführt:
// Zustand: Clientsocket inaktiv procedure TFrmClient.ClientSocketConnecting (Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Verbindung wird aufgebaut');
end;
procedure TFrmClient.ClientSocketConnect (Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Verbindung hergestellt');
end;
// Zustand: Clientsocket aktiv (mit einem Serversocket verbunden) // Mögliche Ereignisse: procedure TFrmClient.ClientSocketRead (Sender: TObject; Socket: TCustomWinSocket);
begin
...
end;
procedure TFrmClient.ClientSocketWrite (Sender: TObject; Socket: TCustomWinSocket);
begin
...
end;
procedure TFrmClient.ClientSocketError (Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErroeEvent; var ErrorCode: Integer);
begin
MemStatus.Lines.Add ('Status: Fehler ' + IntToStr(ErrorCode));
ErrorCode := 0
end;
procedure TFrmClient.ClientSocketDisconnect (Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Verbindung wird getrennt');
end;
// Zustand: Clientsocket inaktiv |
Analog einige Ereignis-Methoden des Serversockets
// Zustand: Server aktiv
procedure TFrmServer.ServerSocketAccept (Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Client verbunden');
Socket.SendText ('Willkommen, Client ... ')
end;
procedure TFrmServer.ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Client verbunden');
Socket.SendText ('Willkommen, Client ... ')
end;
procedure TFrmServer.ServerSocketClientRead (Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add (Socket.ReceiveText);
Socket.SendText ('Hallo, Peter ...');
end;
procedure TFrmClient.ClientSocketError (Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErroeEvent; var ErrorCode: Integer);
begin
MemStatus.Lines.Add ('Status: Fehler ' + IntToStr(ErrorCode));
ErrorCode := 0
end;
procedure TFrmServer.ServerSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
MemStatus.Lines.Add ('Status: Client abgemeldet');
Socket.SendText ('Tschüss, Client ... ')
end;
|
Wird das Programm Kontakt1 um diese Ereignis-Methoden
ergänzt, ergeben sich für die beiden Fenster die weiter oben
abgebildeten Ausgabe in den Memo-Feldern.
Download Programm Kontakt1
(Delphi 7): Kontakt1.zip
Das vorige und die folgenden Programmierbeispiele sind so angelegt, dass der Serversocket und der Clientsocket im gleichen Programm auf demselben Rechner laufen. Das vereinfacht hier die Programmentwicklung und ermöglicht die Demonstration der Zusammenhänge auf einem einzigen Rechner. Tatsächlich laufen Server- und Client-Programm üblicherweise auf verschiedenen Rechnern.
Zur Demonstration dieses Sachverhaltes dient das Programm Kontakt2. Es besteht aus den beiden Programmen Server2 und Client2, die auf verschiedenen Rechnern gestartet werden können. Im Gegensatz zum vorigen Programm muss der Clientsocket dann noch an die IP Adresse und die Portnummer des Server-Sockets angepasst werden. Das Fenster des Client-Programms hat hierfür zusätzliche Eingabefelder EdAdresse und EdPort.
Download Programm Kontakt2 (Delphi 7): Kontakt2.zip
Alle noch folgenden Programmbeispiele können - und sollten - in gleicher Weise zu "echten" Client-Server-Anwendungen erweitert werden.