Einzelnen Beitrag anzeigen

hsg

Registriert seit: 24. Apr 2006
Ort: Wustermark
354 Beiträge
 
Delphi 10.3 Rio
 
#28

AW: Indy TCPServer beenden mit toten Clients

  Alt 14. Jun 2012, 06:59
Hallo Data,

Hi Hsg,

ich habe mir das ganze gerade mal auf die schnelle angeschaut
und ein paar kleine Änderungen gemacht ohne Testmöglichkeit, deshalb ohne Gewähr auf Richtig.
Es war nur ein kleiner Fehler drin

Erstmal habe ich innerhalb der Procedure DisConnectAllClients
das Senden mit Try except gekapselt, damit auch alle Clients wirklich die Nachricht bekommen
und nicht wenn bei z.b. Client2 eine Exception während des Senden auftritt und die restlichen Clients dann
nicht mehr benachrichtigt werden.
Des Weiteren habe ich LockList und UnlockList mit Try finally abgesichert !! Unbedingt zu empfehlen !!!

Ein weiterer sehr entschiedener Punkt ist:
Wo wird DisConnectAllClients aufgerufen, in Deinem Sourcecode Auszug ist kein Aufruf davon zu finden!
Und gerade im Setter der Active Eigenschaft Deines Servers, solltest Du vorm setzen der Eigenschaft
Active = false, woher alle Clients benachrichtigen, das der Server heruntergefahen wird und die Clients
die Verbindung trennen sollen.
Ich habe ein paar Try-Excepts rausgeworfen gehabt, damit ich sicherstellen konnte, dass nicht alle Exceptions abgefangen werden und nicht mehr durchgereicht werden. Mit dem Try...finally hast du natürlich recht.

Das DisconnectAllClients wird vom Hauptfenster aufgerufen. Ich hatte es ursprünglich mal an der SetActive-Stelle drin, gab dann aber Probleme beim Beenden auch unter normalen Bedingungen. Das Application.ProcessMessages ist an der Stelle entscheidend, denn ansonsten können die Clients sich nicht erfolgreich abmelden. Das gesamte Programm ist so geschrieben, dass es sowohl als Dienst als auch als Fenster-Programm kompiliert werden kann. Daher habe ich in der uPdaServer.pas kein definiertes Applikations-Fenster zur Verfügung und deswegen den entsprechenden Aufruf von DisConnectAllClients in die Verwaltungsroutine geschoben.

Delphi-Quellcode:
procedure TMainForm.StopServer;
var
  i: Integer;
begin
  if oServer <> nil then begin

    mleInfo.Lines.Add('Warten auf Abmeldung Clients');
    oServer.DisConnectAllClients();
    for i := 0 to 3 do begin
      Sleep(1000);
      Application.ProcessMessages();
    end; // for i := 0 to
    mleInfo.Lines.Add('Server wird gestoppt');

    oServer.Active := False;
    FreeAndNil(oServer);

    btnClearLog.Click;
    btnServer.Tag := 0;
    btnServer.Caption := 'Server starten';
    btnGetClientList.Enabled := False;
  end;
end;
Das sollte Dein Problem jetzt aber lösen (hoff ich)

Greetz Data
leider nein

Gruß
hsg

Edit:
iClientCount ist beim oServer.Active := false größer als Null. Der TimeOut ist in deiner Schleife die Abbruchbedingung.

Geändert von hsg (14. Jun 2012 um 07:30 Uhr)
  Mit Zitat antworten Zitat