Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen (https://www.delphipraxis.net/174886-dauerhafte-onlineueberpruefung-mit-serverseitigen-befehlen.html)

Delphi-Narr 16. Mai 2013 11:37

Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Hallo,

ich habe ein Problem beziehungsweise eine generelle Frage.
Es geht um ein Server-Client System, bei dem ein Server auf Clients wartet und unter bestimmten Bedingungen Daten versendet.
Beim Systemstart des Clients versucht der Client über TCP eine Verbindung aufzubauen und versucht dies immer wieder, sofern keine Verbindung besteht.
Nach der Verbindung schickt der Client eine "Statusmeldung" an den Server und wiederholt dies immer dann, wenn sich der Status ändert. Das passiert jedoch eher selten (zumindest ohne serverseitiges Eingreifen).
Es handelt sich um ein Netzwerk von bis zu 200 Rechnern im lokalen Netzwerk und zusätzlichen Rechnern, falls Nurzer das System von zu Hause aus nutzen wollen.

Generelle Frage: Ist es bei einer doch recht hohen (bis theoretisch unbegrenzten) Anzahl an Rechnern sinnvoll, die Verbindung aufrecht zu erhalten?!

Der Server dient generell dazu, zu überprüfen, ob ein Client verfügbar ist und trägt dies in eine Datenbank ein.
Der Server erhält dann (manchmal) die Aufgabe, bestimmte Befehle an einen Client zu senden - dazu muss aber eine Verbindung bestehen, wenn der Client nicht selbst zum Server werden soll, was aufgrund der Firewall nicht geht.
Ich hatte auch schon an eine Art "Befehlswarteschlange" gedacht, bei der sich der Client alle 30 Sekunden mal verbindet und so die Möglichkeit bietet, die Befehle zu empfangen. Diese Zeitverzögerung sollte aber eigentlich auch nicht sein.

Bisher läuft das Ganze über die ursprüngliche Methode einer Dauerverbindung, doch viele Clients verlieren zwischendurch einfach die Verbindung (ohne erkennbaren Grund) und verbinden sich auch nicht erneut, wenn man den Server beispielsweise neustartet.

Kleiner Auszug aus einem Timer des Clients:
Delphi-Quellcode:
if (TCPClient.Connected) then
      begin
        if (Statusupdate) then  // Wenn sich der Status geändert hat
          begin
            Data.Lockstate:=Lockstate;
            Data.Username:=GetUsername;
            Data.PCName:=GetComputerName;
            Data.CPU:=CPUName;
            Data.RAM:=IntToStr(gettotalphysmemory div (1024*1024))+' MB';
            Data.Boardname:=BoardName;
            Data.BoardManufacturer:=BoardManu;
            Data.Mac:=GetMACAdress;
            Data.Version:=Version;

            ClientMac:=Data.Mac;

            if Data.Boardname='Unknown' then
              Data.BoardName:=BoardNameWMIC;
            if Data.BoardManufacturer='Unknown' then
              Data.BoardManufacturer:=BoardManuWMIC;
           

            buf := RawToBytes(Data, SizeOf(TClientInfo));

            TCPClient.IOHandler.Write(Buf);
            Username:=User;
            LastState:=Lockstate;
          end;
        CheckCMD(); // Überprüfen, ob der Server was gesendet hat
      end
    else
      begin
        try
          TCPClient.Connect;  
          Username:='';
          LastState:=4; // Nächstes Mal auf jeden Fall Status senden
        except          
          Username:='';
          LastState:=4;
        end;
      end;
Gibt es da ein paar Ideen zu?

PS: Ich verwende die Indy Komponenten

Der schöne Günther 16. Mai 2013 12:03

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Die Befürchtung betrifft doch eigentlich nur den Server, dass er nicht damit zurechtkommt, so viele Verbindungen gleichzeitig offen zu halten, oder? Mein Windows 7-Desktop lauscht im Moment gerade schon auf 70 Ports gleichzeitig, ein halbwegs ernstzunehmender Server wird auch mit zwei- dreihundert offenen Verbindungen wohl zurechtkommen.

Aber das ist nicht mein Fachgebiet, Menschenleben sollte man von meiner Aussage jetzt besser nicht abhängig machen.

Ab wann gilt der Client beim Server eigentlich wieder als abgemeldet? Wenn innerhalb von ... 45 Sekunden keine Meldung mehr von ihm kam?

Warum ein Client die Verbindung verlieren sollte wüsste ich spontan auch nicht.

p80286 16. Mai 2013 12:15

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Eigentlich sollte es so sein, daß zwei Rechner nur dann in Verbindung treten wenn sie sich etwas zu sagen haben. Die permanent offene Verbindung,mit permanentem Versand von Prüfnachrichten ist einfach nur Verschwendung und bringt überhaupt nichts, wenn im Moment der Übertragung der wichtigen Daten die Verbindung zusammenbricht. Falls so etwas wirklich notwendig ist, sollte das dannaber auch über ein physisch eigenständiges Netz abgewickelt werden.

Gruß
K-H

Sir Rufo 16. Mai 2013 12:38

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Mal abgesehen davon, dass man dass auch mit Bei Google suchenMicrosoft-Message-Queue (oder einem anderen MQ Dienst) abtüten könnte.

Ich würde die Clients alle x Sekunden mit dem Server verbinden und dort nach Aufgaben anfragen lassen.
Ist eine Aufgabe vorhanden, diese Aufgabe abholen, abarbeiten und die Aufgabe als erledigt melden.
Dann direkt wieder nach einer Aufgabe suchen.

Ist keine Aufgabe mehr vorhanden, dann wieder alle x Sekunden fragen.

Eine Verbindung zum Server besteht somit nur während der Abfrage, dem Abholen und der Rückmeldung.

hathor 16. Mai 2013 12:51

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Hier gibt es Infos:

So ermitteln Sie den Verlust von Client/Server-Verbindung

http://support.microsoft.com/kb/140325

Tags:
halb-offene Verbindung
KeepAlive
KeepAliveInterval
KeepAliveTime

Delphi-Narr 16. Mai 2013 13:57

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
@Der schöne Günther:
Bisher gilt der Client als abgemeldet, wenn er die Verbindung verliert, die (bisher) dauerhaft offenhalten wird.

An sich stimme ich zu, dass die Verbindung nicht dauerhaft aufgehalten werden sollte, doch um den Client als effektives Tool zu nutzen, müssen
die Aufgaben recht schnell abgearbeitet werden. Darunter fallen zum Beispiel auch Screenshots und die sollen auf jeden Fall aktuell sein, wenn der Server anfragt.
Während der eigentlichen Datenübertragung bricht die Verbindung nicht ab! Der Record kommt immer komplett an und verursacht keine Fehler. Nur während der "Wartephase"
verabschiedet sich der Client dann mal, um teilweise nach 2 Sekunden wieder zu verbinden.
Es handelt sich um einen Windows Server 2008, der mit den Verbindungen an sich durchaus klarkommen sollte.
Einzige Möglichkeit wäre vielleicht noch, dass das Serverprogramm überlastet, wenn es bei vielen verbundenen Clients auch noch viele "Kommandoverbindungen" gibt, welche dem Serverprogramm sagen,
welcher Client welchen Befehl ausführen soll.
Wenn alle 10 Sekunden 60 Anfragen auf einmal kommen, sollte das den Server aber eigentlich nicht aus der Bahn werfen.
Ich gucke mir mal die Links an, danke!

sx2008 16. Mai 2013 17:58

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Switches und Router müssen ihre internen ARP Caches (Zuordnung MAC <-> IP) klein halten und löschen die Einträge nach einer bestimmten Zeit.
Wenn die Endteilnehmer einer TCP-Verbindung eine bestimmte Zeit nicht miteinander reden, dann kann die Verbindung getrennt werden ohne dass es die Endpunkte gleich mitbekommen.
Möchte man das vermeiden, kann man in periodischen Abständen einen NOOP-Befehl verschicken.

Natürlich muss der NOOP-Befehl im Protokoll vorgesehen werden.
Meine Empfehlung: im Protokoll sollte sowohl für den Client als auch für Server ein NOOP-Befehl/Message vorgesehen werden.

WinSock bietet auch die Möglichkeit Keep-Alive Pakete zu verschicken. (siehe Info von hathor)
Client und Server bekommen davon nichts mit.
Allerdings hängt es vor der Windows Version ab wie gut das funktioniert und man muss in die Tiefen von WinSock eintauchen.
Bei älteren Windows-Versionen muss man an der Registry herumschrauben und ändert das Verhalten aller TCP/IP-Verbindungen.
Falls möglich würde ich den NOOP-Befehl vorziehen.

Delphi-Narr 16. Mai 2013 18:22

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
So ein NOOP-Befehl ist eine gute Idee. Das mit den Switches und Routern war mir so nicht bewusst.
Von Zeit zu Zeit einen "sinnlosen" Befehl zu senden ist auf jeden Fall kein Problem! Kann der Client mit einem Befehl vom Server nichts anfangen,
reagiert er jetzt schon einfach nicht. So ist das in dieser Richtung auf jeden Fall sehr einfach zu realisieren. Muss die Kommunikation denn
zwangsweise in beide Richtungen stattfinden, damit die Verbindung nicht gekappt wird oder würde das schon reichen?
Danke auf jeden Fall für die Antwort!

sx2008 16. Mai 2013 18:46

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1215559)
Muss die Kommunikation denn zwangsweise in beide Richtungen stattfinden, damit die Verbindung nicht gekappt wird oder würde das schon reichen?

Eine Richtung reicht.
Ich würde im Protokoll nur beide Richtungen vorsehen, damit man sich alle Möglichkeiten offen hält.
Ein NOOP-Befehl sollte von der anderen Seite nicht bestätigt sondern ignoriert werden.

Furtbichler 17. Mai 2013 05:37

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Ich würde ein Ping-Pong implementieren. Der Client sendet alle X Sekunden ein cund erwartet ein "Jupp" vom Server. Der Server erwartet ein "Bist Du noch da?" alle X+n Sekunden.

Kommt das "Jupp" nicht, beendet der Client die Verbindung, die ja offensichtlich ins Nirvana geführt hat.
Bekommt der Server die nächste Anfrage "Bist Du noch Da?" nach X+n Sekunden nicht, kappt er die Verbindung.

Der Client versucht bei verlorener Verbindung, diese wieder aufzubauen.

Eine ständig offene Verbindung ist nur bei ständigem Datenfluß zu erwarten, tut aber eigentlich auch nicht weh. Wenn man jedoch eh nur selten etwas zu verschicken hat, dann kann man die Verbindung jedes Mal neu aufbauen. Das dauert aber manchmal etwas, weil die Netzwerkkomponenten teilweise erst aufwachen müssen (jedenfalls war das mein Eindruck). Bei einem Kunden war das ein Problem, denn dann war der Server beim 1. Verbindungsversuch nicht erreichbar, also musste man mehrmals versuchen und dann noch den Timeout erhöhen. Also beim ersten Versuch mit kurzem Timeout und dann den Timeout erhöhen.

Wenn Du mit abgebrochenen Verbindungen leben musst (WLAN außer Reichweite z.B.) dann solltest Du das vielleicht einfach ins Kalkül nehmen.

Ich persönlich würde dann vermutlich Daten nur verschicken, wenn es etwas zu sagen gibt, oder benötigst Du auch die Information, das der Client auch 'da', also 'online' ist?

Delphi-Narr 17. Mai 2013 10:29

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Da die Serveranwendung den Onlinestatus in eine Datenbank einträgt, die dann hinterher von anderen Programmen ausgelesen werden kann,
muss der Server auch immer wissen, ob der Client noch da ist.
Und der Server muss auch jederzeit die Möglichkeit haben, dem Client etwas zu "sagen" - wenn der Client dann grade offline ist, ist das nicht so optimal.
Entweder verschwindet der Befehl im Nirvana, weil der Server den Client für dauerhaft offline hält, oder der Befehl wird gecacht und dann viel zu spät ausgeführt,
wenn er schon gar nicht mehr benötigt wird. Darum muss die Verbindung an sich immer offen gehalten werden.

Ich werde dann mal eine "Sinnlos-Kommunikation" einbauen.

p80286 17. Mai 2013 11:45

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Da die Serveranwendung den Onlinestatus in eine Datenbank einträgt, die dann hinterher von anderen Programmen ausgelesen werden kann,
muss der Server auch immer wissen, ob der Client noch da ist.

alles was der Server weiß, ist daß zu einem bestimmten Zeitpunkt X der Client geantwortet hat.
Nicht mehr nicht weniger.

Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Und der Server muss auch jederzeit die Möglichkeit haben, dem Client etwas zu "sagen" - wenn der Client dann grade offline ist, ist das nicht so optimal.

Darum lassen sich viele Protokolle ja den Empfang auch quittieren.

Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Entweder verschwindet der Befehl im Nirvana, weil der Server den Client für dauerhaft offline hält, oder der Befehl wird gecacht und dann viel zu spät ausgeführt,wenn er schon gar nicht mehr benötigt wird.

Es soll auch für Daten/Befehle so etwas wie ein Verfallsdatum geben (TimeToLive)

Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Darum muss die Verbindung an sich immer offen gehalten werden.

Ich werde dann mal eine "Sinnlos-Kommunikation" einbauen.

:gruebel:

Gruß
K-H

mjustin 17. Mai 2013 12:54

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von p80286 (Beitrag 1215525)
Die permanent offene Verbindung,mit permanentem Versand von Prüfnachrichten ist einfach nur Verschwendung und bringt überhaupt nichts, wenn im Moment der Übertragung der wichtigen Daten die Verbindung zusammenbricht.

Bei TCP ist das Problem leider, dass der Socket - ohne aktiv zu werden - eine zusammengebrochene Verbindung nicht von einer noch bestehenden Verbindung unterscheiden kann.

Das regelmäßige Senden von heart-beat Signalen (auf der Protokollebene) ist ein in der Praxis üblicher Weg, einen Verbindungszusammenbruch auch dann festzustellen, wenn gerade keine Nutzdaten übertragen werden. Es verursacht weniger Netzwerktraffic als ein ständiges Auf- und Abbauen der Verbindung.

p.s. In Netzwerken mit Network Address Translation NAT sind heart-beats auch eine Möglichkeit, das Trennen der Verbindung durch das NAT Gerät zu vermeiden (NAT arbeitet mit einer Tabelle der Verbindungen, und Tabelleneinträge werden nach einer bestimmten Zeit der Inaktivität entfernt).

Delphi-Narr 18. Mai 2013 09:38

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von p80286 (Beitrag 1215633)
Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Da die Serveranwendung den Onlinestatus in eine Datenbank einträgt, die dann hinterher von anderen Programmen ausgelesen werden kann,
muss der Server auch immer wissen, ob der Client noch da ist.

alles was der Server weiß, ist daß zu einem bestimmten Zeitpunkt X der Client geantwortet hat.
Nicht mehr nicht weniger.

Das stimmt, aber wenn der Client ab und an mal etwas schickt, hält ein Switch dann die Verbindung offen (wenn ich das hier alles richtig verstanden habe)
und es könnte einzig das Problem auftreten, dass Server oder Client abschmieren. Wenn das der Fall ist, wird die Gegenseite das mit der Zeit aber auch herausfinden.

Zitat:

Zitat von p80286 (Beitrag 1215633)
Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Entweder verschwindet der Befehl im Nirvana, weil der Server den Client für dauerhaft offline hält, oder der Befehl wird gecacht und dann viel zu spät ausgeführt,wenn er schon gar nicht mehr benötigt wird.

Es soll auch für Daten/Befehle so etwas wie ein Verfallsdatum geben (TimeToLive)

An sich eine gute Idee, aber weder Server noch Client wissen, wie der Nutzer reagiert, wenn sein Befehl nicht sofort ausgeführt wird.
Darum kann ich eigentlich nicht global so eine Zeit festlegen.

Zitat:

Zitat von p80286 (Beitrag 1215633)
Zitat:

Zitat von Delphi-Narr (Beitrag 1215619)
Darum muss die Verbindung an sich immer offen gehalten werden.

Ich werde dann mal eine "Sinnlos-Kommunikation" einbauen.

:gruebel:

Ich meine damit, dass Server und Client zwischendurch einfach mal ein "Hallo, wie geht's?" schicken
und wenn es keine Antwort gibt, trennen sie die Verbindung und versuchen es erneut. Die übertragenen Daten werden
aber vom Server bzw. Client nicht weiter verarbeitet und in "komplexere" und rechenaufwendige Prozeduren geleitet.
Ein bisschen Smalltalk quasi ;)

Furtbichler 18. Mai 2013 10:14

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1215711)
und es könnte einzig das Problem auftreten, dass Server oder Client abschmieren.

Oder ein Wackelkontakt, oder Kabel wird rausgezogen, oder ein falsch konfigurierter Switch, oder überlastete Switches, oder WLAN, oder Internet, oder die Putzfrau, oder, oder, oder.

Bei TCP ist es nicht so, das Du Pech hast, wenn etwas nicht läuft, sondern Glück hast, das etwas läuft. Du musst hier wirklich Hosenträger, Gürtel und Antackern-An-Den-Bierbauch implementieren. Und zwar im Protokoll.

Also:
1. Heartbeats wie beschrieben.
2. Pack dein Telegramm in einen Frame mit Längenangabe: <STX><Len><Data><ETX> (vielleicht sogar eine Prüfsumme). Begrenze 'Len', denn auch hier kann Müll stehen, und Du willst ja nicht 300Gig an Daten lesen...
3. Jedes Telegramm wird per ACK/NAK beantwortet. Ich hatte hier mal ein Protokoll mit Checksum, was bei TCP eigentlich überflüssig ist, aber trotzdem bei einem Kunden in Indien diverse NAKs Aufgrund fehlerhafter Prüfsummen.
4. Jedes Telegramm erhält zudem eine eindeutige ID (fortlaufende Nummer reicht)

Wenn hier irgendetwas schief läuft (Heartbeat bleibt aus, Antwort kommt nicht, Länge zu groß) wird die Verbindung gnadenlos gekappt.

Mach Dir lieber mehr Gedanken über ein robustes und idiotensicheres Protokoll. Wenn Du dich darauf verlassen kannst, dann macht TCP sogar richtig Spaß.

Gibts da eigentlich nix Fertiges?

Delphi-Narr 18. Mai 2013 11:32

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
Zitat:

Zitat von Furtbichler (Beitrag 1215714)
Zitat:

Zitat von Delphi-Narr (Beitrag 1215711)
und es könnte einzig das Problem auftreten, dass Server oder Client abschmieren.

Oder ein Wackelkontakt, oder Kabel wird rausgezogen, oder ein falsch konfigurierter Switch, oder überlastete Switches, oder WLAN, oder Internet, oder die Putzfrau, oder, oder, oder.

Aber auch wenn die Putzfrau sich austobt, wird der Smalltalk abgewürgt.
Die übertragenen Daten sind generell nicht gigantisch. Der Empfang von Kommandos wird bereits dadurch bestätigt, dass der Client das Empfangene einfach nochmal zurückschickt.

Ich werde mich aber jetzt mal an eine geschlossenes Protokoll setzen, wo das alles eingebaut ist und nicht viele einzelne Bruchstücke.

tgvoelker 26. Mai 2013 20:21

AW: Dauerhafte "Onlineüberprüfung" mit Serverseitigen Befehlen
 
TCP implementiert immer Verbindungen mit Status. "Keepalive" benötigst für TCP-Verbindungen nuraus einem Grund: um zwischen Server und Client vorhandenen Firewalls davon abzuhalten, die Verbindung nach Inaktivität zu löschen, während Server und/oder Client diese noch als "bestehend" ansehen.

Du erkennst einen Verbindungsverlust/abbau von Seiten des Clients auf Serverseite in zwei Fällen: erstens wenn der Client die Verbindung beendet und zweitens, wenn der Server was an den Client schickt und darauf kein ACK bekommt, bis der Retransmission Timer abgelaufen ist. Die Verbindungskontrolle erfolgt dabei auf Protokollebene.

Das Problem dabei ist, daß die Anti-DoS-Mechanismen von Firewalls restriktive Schranken für die Anzahl und Zeitdauer inaktiver Verbindungen haben (Hintergrund dafür ist, daß DDoS-Angriffe mit halboffenen Verbindungen geführt wurden) - was dazu führt, daß die Firewalls TCP-Verbindungen ohne periodische Aktivität schon nach kurzer Zeit aus der Verbindungsliste schmeißen. Beispiel: Ich hatte mal einen Levelone Router, der aktive FTP-Sitzung abgebrichen hat, wenn die Übertragung einer einzelnen Datei länger als 10 Minuten gedauert hat - das Ding hat FTP-DATA offengelassen und FTP-CONTROL geschlossen. Aufgefallen ist das erst am Ende der Übertragung, bei kleinen dateien ging alles.

Sauberer kannst Du das mit UDP oder auch mit ICMP implementieren, aber das erfordert, daß die Clients nicht hinter einer NAT-Firewall stecken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz