![]() |
ClientSocket soll viele Server schnell abfragen
Hallo und einen guten Morgen in die Runde.
Ich bräuchte mal einen Denkanstoß. Ich habe eine kleine Hilfsanwendung mit einem ClientSocket realisiert mit dem ich mich mit verschiedenen Servern verbinden kann (CNC-Maschinen) und dort per ASCII Zeichenfolge verschiedene Daten abfrage. Es sind nur ein paar wenige Maschinen, ich wähle eine aus einer Liste aus, verbinde mich und sende per Klick eine Abfrage wenn die Verbindung steht oder auch nicht wenn ich nur sehen will ob sie online ist. Sollte eine Maschine nicht eingeschaltet sein dauert es etwa 20 Sec. bis ich die Rückmeldung bekomme. Solange muss ich warten. Bei den paar Maschinen kein Problem aaaaber jetzt sollen noch 50 weitere dazu. Es sind ältere Maschinen mit reinen CNC Steuerungen die an Kommunikation nicht wirklich etwas können. Dort werden jetzt Digital zu Ehternet Klemmen eingesetzt die auch per ASCII abgefragt werden können. Also nicht viel anders als bisher. Ich möchte das jetzt gerne automatisieren, also zyklisch alle xx sec. alle Maschinen abfragen. Wenn jetzt natürlich einige nicht online sind würde ich bei einer seriellen Abfrage sehr schnell viel Zeit verlieren die den nächsten Abfragezuklus vielleicht schon überschreitet. Wie stelle ich das am geschicktesten und elegantesten an? Ich hab schon hier im Forum nach etwas vergleichbarem gesucht aber entweder fehlen mir die richtigen Suchbegriffe oder es wurde in der Form noch nicht behandelt. Bringt mich mal bitte jemand auf die richtige Spur. Gibt es irgendwo Beispiele die ähnlich geartet sind? Ich denke der Quelltext der vorhandene Hilfsanwendung spielt hier keine weitere Rolle. |
AW: ClientSocket soll viele Server schnell abfragen
Du kannst einfach eine
![]() Alternativ kannst du natürlich auch gleich einen richtigen Thread benutzen (bzw. diese Schleife im Thread). Das wäre sicher die beste Lösung, aber eben auch mit etwas Aufwand verbunden. |
AW: ClientSocket soll viele Server schnell abfragen
Hallo,
ich würde auch Thread(s) benutzen, die eine Queue füllen mit den aktuellen Online-Maschinen. Im Prinzip laufen x Threads, deren einzige Aufgabe es ist, den Online-Status der x Maschinen zu prüfen/zu aktualisieren. Die 20 Sekunden sind übrigens der Standard-Timeout von Windows. |
AW: ClientSocket soll viele Server schnell abfragen
Da muss ich mich etwas einarbeiten, das sind momentan noch Böhmische Dörfer für mich.
|
AW: ClientSocket soll viele Server schnell abfragen
Zitat:
|
AW: ClientSocket soll viele Server schnell abfragen
Nun ja, so was wäre möglich
Delphi-Quellcode:
var
addresses: tArray<string>; begin addresses := ['a', 'b', 'c']; TParallel.&For(Low(addresses), High(addresses), procedure(index: Integer) var adr: string; begin adr := addresses[index]; // mach was mit adr end); end; |
AW: ClientSocket soll viele Server schnell abfragen
Hmm..
Optional könntest Du auch vorher per PING mit nem TimeOut von einer Sekunde (sollte im lokalen Netz reichen) abfragen.. Geht natürlich nur, wenn die Ethernetkarten der Maschinen ein Ping erlauben. Aber so würdest Du schon wissen, ob sie eingeschaltet sind, bevor Du per TCP/IP dann eine Verbindung versuchst aufzubauen. |
AW: ClientSocket soll viele Server schnell abfragen
Die Lösung via eigenem Thread wäre meiner Meinung nach von Vorteil, wenn das Abfrageintervall kürzer sein soll, als das maximal mögliche Timeout. Bei Verwendung von eigenen Threads könntest du dir eine Lösung programmieren, die vor dem Anlegen eines neuen Threads erst einmal die Liste der laufenden Threads durchgeht und nachschaut, ob zu der gewünschten Maschiene bereits ein noch offener Verbindungsversuch gestartet ist.
|
AW: ClientSocket soll viele Server schnell abfragen
Schau dir mal die ICSOverbyte WinSock Komponente an.
Alles ist Event gesteuert, nicht blockierend; dein Thread muss also zum Beispiel nach einem Connect Versuch (zu einer deiner Maschinen) nicht darauf warten, bis die Gegenstelle antwortet. Du kannst zu allen 101 Maschinen aufs Mal einen Connect Versuch starten und erhältst später via Ereignisse mitgeteilt, ob eine Session zustande gekommen ist, wenn sich ein Socket Status ändert usw. Es ist also völlig egal, wie lange der Verbindungsaufbau zu einer Machine X dauert: Da nicht darauf gewartet wird, ob und wann X antwortet, wird dein Thread nicht blockiert. Ich habe mit ICS ein p2p Spiel programmiert: Ein User, welcher sich einloggt erhält eine nicht unbedingt sehr aktuelle Liste von Spielservern. Das Szenario ist also praktisch identisch. Alles läuft in einem Thread. In deinem Fall genügt für die Kommunikation (mit ICS) sicher der Hauptthread. |
AW: ClientSocket soll viele Server schnell abfragen
Ja die ICS Komponenten kann ich auch empfehlen. Wenn du mit Threads bisher noch nicht viel gemacht hast, dürftest du mit ICS schneller zum gewünschten Ergebnis kommen.
|
AW: ClientSocket soll viele Server schnell abfragen
Ich werde mir die mal ansehen, danke für den Tipp.
|
AW: ClientSocket soll viele Server schnell abfragen
Könnte mir bitte jemand Hilfestellung geben wie ich diese Komponente oder das ganze Paket installiere.
Ich hatte jetzt das ICS-8.58 heruntergeladen und in einem eigenen Verzeichnis entpackt. Steh gerade etwas auf dem Schlauch. :?: |
AW: ClientSocket soll viele Server schnell abfragen
In dem entpackten Verzeichnis gibt es einen "Install" Ordner. Dort das richtige Gruppenprojekt in Delphi öffnen (ich habe "D103Install.groupproj" genommen - für 10.3, VCL only). Das Gruppenprojekt besteht aus einem Runtime- und einem Design-Projekt. Das Runtime-Projekt erzeugen und das Design-Projekt installieren.
Details zu den Gruppenprojekten siehe "ReadMe8.txt": "INSTALLATION USING THE INSTALL PROJECT GROUPS" Wirf anschließend mal einen Blick auf die mitgelieferten Beispiele. Ich denke das hier könnte für dich erst einmal das wichtigste sein: "Samples\Delphi\SocketDemos\OverbyteIcsCliDemo.dpr oj". Da wird ein einfacher TCP Client erstellt. Um auf das Herstellen der Verbindung zu reagieren, musst du dich dann bloß in das "CliSocketSessionConnected"-Event reinhängen. |
AW: ClientSocket soll viele Server schnell abfragen
Wo das entpackte Verzeichnis liegt ist egal oder muss das an einer bestimmten Stelle liegen?
|
AW: ClientSocket soll viele Server schnell abfragen
Zitat:
Sorry, hab das noch nie gemacht. :? Edit: Man sollte besser schauen, hab es gefunden, stand ganz unten. |
AW: ClientSocket soll viele Server schnell abfragen
Pack den Ordner da hin, wo es für dich übersichtlich ist ;-)
In den Beispielprojekten sind relative Pfade angegeben, da ist es also nur wichtig, dass die Verzeichnisstruktur intakt bleibt. Zum Installieren: Wenn ich das "D103Install" Gruppenprojekt lade, wird bei mir oben rechts die Projektübersicht angezeigt. Da sind zwei Projekte drin: OverbyteIcsD103Run.bpl OverbyteIcsD103Design.bpl Das müsste bei dir auch so sein, oder? Die Runtime hast du ja schon erstellt. Nun noch mit rechter Maustaste auf das Design-Projekt klicken und in dem Kontextmenü "Installieren" ausführen. |
AW: ClientSocket soll viele Server schnell abfragen
Irgend etwas hat nicht hingehauen, die Demo läuft nicht. Die Komponenten scheinen nicht vorhanden zu sein.
Ich versuche das noch mal, eigentlich kann man doch nichts verkehrt machen.... |
AW: ClientSocket soll viele Server schnell abfragen
Eine Warnung beim erzeugen:
[dcc32 Warnung] OverbyteIcsD103Run.dpk(157): W1033 Die Unit 'OverbyteIcsSuperObject' wurde implizit in Package 'OverbyteIcsD103Run' importiert |
AW: ClientSocket soll viele Server schnell abfragen
Die Warnung wird mir auch angezeigt, hat aber keine Auswirkung.
Das Beispielprojekt lässt sich bei mir problemlos ausführen. Wurde dir beim Installieren des Design-Projektes angezeigt, dass die Komponenten (eine längere Liste) erfolgreich installiert wurden? |
AW: ClientSocket soll viele Server schnell abfragen
Liste der Anhänge anzeigen (Anzahl: 1)
|
AW: ClientSocket soll viele Server schnell abfragen
Liste der Anhänge anzeigen (Anzahl: 1)
|
AW: ClientSocket soll viele Server schnell abfragen
Liste der Anhänge anzeigen (Anzahl: 1)
Bibliothekspfade gesetzt? "Don´t forget..."
|
AW: ClientSocket soll viele Server schnell abfragen
Nein das habe ich nicht.
Wie mache ich das? |
AW: ClientSocket soll viele Server schnell abfragen
Nein das habe ich nicht.
Wie mache ich das?
Delphi-Quellcode:
{ Don't forget to add your vc32 directory to Delphi library path }
|
AW: ClientSocket soll viele Server schnell abfragen
Liste der Anhänge anzeigen (Anzahl: 2)
Guckst du hier...:wink:
|
AW: ClientSocket soll viele Server schnell abfragen
Die Frage ist ja wo ich dieses VC32 Verzeichnis finde.
|
AW: ClientSocket soll viele Server schnell abfragen
... der Pfad wo die Packages/Pas liegen (Ich kann nur raten. Entpackter Installordner? :gruebel:)
|
AW: ClientSocket soll viele Server schnell abfragen
Meine Güte, nun sagt es ihm doch vernünftig.
Bei Bibliothekspfad fügst du den Pfad hinzu wo die kompilierten Bibliotheken gelandet sind. Bei Suchpfad fügst du den/die Pfad/e hinzu wo die Source Dateien liegen. |
AW: ClientSocket soll viele Server schnell abfragen
Ich musste bei mir nichts an den Pfaden hinzufügen.
Das Demo-Projekt hat in den Projekteinstellungen einen (relativen) Verweis auf das Verzeichnis mit den Quelltext-Dateien. Sofern das Demo-Projekt so ausgeführt wird, wie es in dem Download enthalten war, müsste es eigentlich funktionieren. Wenn man die Komponenten in einem eigenen Projekt benutzt, muss man natürlich noch den Suchpfad ergänzen (global oder des jeweiligen Projektes). Edit: Kompilierte Bibliotheken sind in dem Download nicht enthalten. |
AW: ClientSocket soll viele Server schnell abfragen
Ich hab jetzt alles mögliche versucht aber scheinbar nicht den Richtigen Pfad gefunden. Ich find noch nicht mal ein Verzeichnis wo die installierten Sachen gelandet sind..... :?:
|
AW: ClientSocket soll viele Server schnell abfragen
Zitat:
|
AW: ClientSocket soll viele Server schnell abfragen
Mann ist das eine Aktion. :roll:
Ich hab das jetzt noch mal deinstalliert und dann nochmal neu. Jetzt läuft auch die Demo ohne Änderung irgendwelcher Pfade. Danke euch bis hier erst mal für eure Geduld mit mir. :thumb: Ich schaue mir das jetzt mal in Ruhe an. |
AW: ClientSocket soll viele Server schnell abfragen
Liste der Anhänge anzeigen (Anzahl: 1)
Schließe mal Delphi, starte es wieder und öffne das Beispielprojekt (wirklich erst einmal nur öffnen). Wird dabei eine Fehlermeldung (siehe Anhang) angezeigt?
Edit: Ah Super :) |
AW: ClientSocket soll viele Server schnell abfragen
Heute hatte ich zeit wieder etwas weiter zu machen. Ich muß sagen ich tue mich echt schwer zumal mein Tagesgeschäft hier nicht nur aus Programmieren besteht. Zwischendurch immer wieder etwas anderes tun zu müssen ist da kontraproduktiv.
Mit dem Beispiel hab ich etwas herum probiert bekomme es aber nicht mal hin zwei Maschinen abzufragen. Mit einer funktioniert es problemlos. Wenn ich das alles richtig verstehe müsste ich ja für jede abzufragende Maschine eine eigenen WSocket nehmen und davon die Ereignisse in eigenen Proceduren verarbeiten um die Ergebnisse dann irgendwo hin zu schreiben. |
AW: ClientSocket soll viele Server schnell abfragen
Mal ganz grundsätzlich:
Du könntest Dein Programm ja 50 mal starten, um 50 Maschinen abzufragen. Da läuft also jede Abfrage in einem eigenen Prozess. Du kannst aber auch in Deinem Programm 50 Threads laufen lassen und in jedem wieder eine eigenständige Abfrage. Ein Thread ist auch ein eigenständiger Prozess. Dann musst Du alles, was benötigt wird in dem Thread instanziieren. Ein Problem ist die Ein- und Ausgabe. Die Eingabe (Verbindung zur jeweiligen Maschine) kannst Du im Thread-Konstruktor übergeben. Das Ergebnis (z.B. Schreiben in ein Memo) muss mit dem Mainthread synchronisiert werden. Mit parallelen Schleifen habe ich noch nichts gemacht aber die sind letztlich auch nur eine andere Darstellung von Threads. |
AW: ClientSocket soll viele Server schnell abfragen
Bei Verwendung von den ICS Komponenten werden keine Threads benötigt - die laufen asynchron und behindern sich damit nicht gegenseitig.
Mal ganz grob skizziert, wie der Test der Verbindungen aussehen könnte:
Delphi-Quellcode:
TNotifyConnectionResult = procedure(const AIp: string; const AErrorCode: Integer; const AInstance: TTestConnection) of object;
TTestConnection = class private FClientSocket: TWSocket; FNotifyEvent: TNotifyConnectionResult; procedure OnClientSessionConnected(Sender: TObject; ErrCode: Word); public procedure TestConnection(const AIp: string; const ANotifyEvent: TNotifyConnectionResult); end; TTestForm = class private FListOfIpAddresses: TStringList; procedure NotifyConnectionResult(const AIp: string; const AErrorCode: Integer; const AInstance: TTestConnection); procedure TestAllConnections; end; implementation procedure TTestConnection.TestConnection(const AIp: string; const ANotifyEvent: TNotifyConnectionResult); begin FNotifyEvent := ANotifyEvent; FClientSocket.Addr := AIP; FClientSocket.Port := cDefaultPort; //oder Port mitgeben FClientSocket.OnSessionConnected := OnClientSessionConnected; FClientSocket.Connect; end; procedure TTestConnection.OnClientSessionConnected(Sender: TObject; ErrCode: Word); begin FNotifyEvent(FClientSocket.Addr, ErrCode, Self); //Code 0: Verbunden, sonst Fehler end; //---- procedure TTestForm.TestAllConnections; var IP: string; Test: TTestConnection; begin for IP in FListOfIpAddresses do begin Test := TTestConnection.Create; Test.TestConnection(IP, NotifyConnectionResult); end; end; procedure TTestForm.NotifyConnectionResult(const AIp: string; const AErrorCode: Integer; const AInstance: TTestConnection); begin if AErrorCode = 0 then //Erfolgreiche Verbindung anzeigen else //Verbindung fehlgeschlagen anzeigen AInstance.Free; end; |
AW: ClientSocket soll viele Server schnell abfragen
Zitat:
Wenn du vorher etwas üben willst, empfehle ich dir, dich erst einmal auf eine Maschine zu konzentrieren. Knall eine TWSocket Komponente (WSocket1) auf ein Fenster und definiere via Obejektinspektor was in den Fällen OnDataAvailable, OnChangeState, und evt. später OnError, OnSocksError, OnSessionClosed geschehen soll. Sobald alles läuft... Mehrere Maschinen. Wie du schreibst, nimmst du für jede Verbindung/Maschine einen Socket. Diese Sockets erzeugst du bei Bedarf zur Laufzeit (auf deinem Form befindet sich also immer noch nur eine TWSocket Komponente WSocket1). Ereignisse wie OnDataAvailable, OnChangeState musst für jeden dieser Sockets verarbeiten. Dies hast du aber mit WSocket1 bereits erledigt. Du biegst einfach OnDataAvailable, OnChangeState um: MeinZurLaufZeitErzeugterSocket.OnDataAvailable := WSocket1DataAvailable; MeinZurLaufZeitErzeugterSocket.OnChangeState := WSocket1ChangeState; Damit du unterscheiden kannst, welcher deiner Sockets (Maschinen) ein Ereignis (wie zum Beispiel OnDataAvailable) ausgelöst hat, kannst du wie ensaron zeigt die IPAdresse (und allenfalls den Port) der Zieladresse (Maschine) nutzen. Oder du verwendest die Eigenschaft Tag von TWSocket: MeinZurLaufZeitErzeugterSocket.Tag := irgendEineEindeutigeNummer; In WSocket1DataAvailable(Sender: TObject; Error: Word); kannst du dann via welcherSocketSendetDaten := ( Sender as TWSocket ).tag; ermitteln, über welche Verbindung Daten ankommen. |
AW: ClientSocket soll viele Server schnell abfragen
Zitat:
Zitat:
Hab heut noch ein paar andere Dinge zu tun. |
AW: ClientSocket soll viele Server schnell abfragen
Ist es richtig, dass dann die angefragten CNC-Maschinen aber auch asynchron arbeiten können müssen?
Ggf. müssten sie also erst umgestellt werden, was möglicherweise gar nicht realisierbar ist? Ist das so richtig? Ich habe nur mal mit asynchronen Sockets unter Delphi experimentiert. Da mussten ja auch Server und Clients auf non blocking gestellt werden. Wenn es sich um existierende Maschinen (Clients) handelt, die man nicht selbst programmiert, könnte das womöglich schwierig werden. Kann sein, dass ich da auch falsch liege. Aber womöglich wird eine ICS-Lösung für Holger schwierig. |
AW: ClientSocket soll viele Server schnell abfragen
@stahli
Nein, nichts vom dem ist richtig. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz