[erledigt] LNet mehrere Verbindungen

Alle Fragen zur Netzwerkkommunikation
Antworten
NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

[erledigt] LNet mehrere Verbindungen

Beitrag von NoCee »

Tach zusammen.

Ich spiele gerade mal wieder mit LNet rum und das Meiste was ich mir vorgenommen habe tut auch ganz brauchbar.
Was ich nicht hinkriege: :(
Einen Server und einen Client
oder
zwei Clients
oder
zwei Server auf verschiedenen Ports
gleichzeitig laufen zu lassen.

Mach ich z.B. einen Server auf Port 5000 und danach einen auf Port 5001 auf (zumindestens versuch ich das),
ist nur letzerer funktionstüchtig.
Gibt LNet das vielleicht gar nicht her?

Helf mir einer mal bitte auf die Sprünge
Besten Dank schon mal
and have a nice day

NoCee
Zuletzt geändert von NoCee am Di 21. Aug 2012, 18:00, insgesamt 1-mal geändert.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: LNet mehrere Verbindungen

Beitrag von Socke »

NoCee hat geschrieben:Mach ich z.B. einen Server auf Port 5000 und danach einen auf Port 5001 auf (zumindestens versuch ich das),
ist nur letzerer funktionstüchtig. t
Gibt LNet das vielleicht gar nicht her?

LNet gibt das her, da es -- nach meinem Verständnis -- nur den Zugriff auf die Betriebssystem-Sockets abstrahiert. Die Frage ist daher: wie machst du das ganze? Ohne Quelltext -- am Besten ein funktionstüchtiges Projekt, in dem der Fehler wie beschrieben auftritt -- wird dir vermutlich niemand weiterhelfen können.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: LNet mehrere Verbindungen

Beitrag von mschnell »

Vermutlich brauchst Du mehrere Threads.

-Michael

NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: LNet mehrere Verbindungen

Beitrag von NoCee »

Danke für die flotte Antworten

Dazu erst noch 2 einfache Fragen:
1) Wie bringt man das Beispiel ins Forum?
So wie ichs gemacht hab oder ist was anderes üblich.
2) Wie bring ich einen Teil vom Quellcode mit dem Aussehen der Lazarus-Ide in dieses Fenster?
Hab ich schon oft gesehen, weiß aber immer noch nicht wies geht.

Hier zum ursprünglichen Problem:
Ich hab wie unten beschrieben im einfachsten Fall mal probiert das "FNet.Listen(PortNr)"
zweimal aufzurufen.
Da ich mich in der Ecke der Anfänger tummle, probiert man das halt mal so
aber schon in der Annahme das das so einfach warscheinlich nicht geht.
Das Prog ist übrigens ein originales Beispiel von LNet (by Ales Katona).
Da weiß ich daß das grundsätzlich mal funktioniert.
Mit einem "zusätzlichen Thread" hab ich da gleich ein Problem, da ich grade mal wage weiß
was das überhaupt darstellt.

Code: Alles auswählen

procedure TForm1.ListenButtonClick(Sender: TObject);
begin
 
 
  if FNet.Listen(5000) then begin
    MemoText.Append('Accepting connections on port 5000');
    FIsServer := True;
  end;
 
 
 
  if FNet.Listen(5001) then begin                                               //meine Erweiterung
    MemoText.Append('Accepting connections on port 5001');       //zeiter Aufruf von FNet.Listen(PortNr)
    FIsServer := True;
  end;
 
 
end;

Danke für eure Hilfe
Ich wünsche ein schönes Wochenende
Gruß
NoCee
Dateianhänge
main.zip
(5.22 KiB) 77-mal heruntergeladen
Zuletzt geändert von Lori am Sa 18. Aug 2012, 08:24, insgesamt 1-mal geändert.
Grund: Highlighter

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: LNet mehrere Verbindungen

Beitrag von mschnell »

NoCee hat geschrieben:Mit einem "zusätzlichen Thread" hab ich da gleich ein Problem, da ich grade mal wage weiß was das überhaupt darstellt.


Ein Thread ist so was ähnliches wie ein zusätzliches gleichzeitig laufendes Programm. Ein Programm besteht also aus mindestens einem Thread (dem sogenannten Mainthread) und beliebig vielen weiteren ("Worker") - Threads. Im Gegensatz zu eigenständigen Programmen verwenden alle Threads eines Programms denselben Speicher und dieselben offenen Dateien. (Das ist die Kurzfassung, es gibt da noch viel zu zu sagen und man kann auch unterschiedliche Arten von Threads erzeugen, das ist hier aber nicht relevant.)

In Lazarus gilt darüber hinaus:
- solange man nichts weiteres tut läuft der "Mainthread"
- Threads erzeugt man am besten als Instanz eines von TThread abgeleiteten Objektes
- nur der Mainthread kann "Event-Orientiert" programmiert werden (der User-Code steht ausschließlich in vom System erzeugte Events (OnClick, OnTimer, ... ), Threads dagegen laufen nur im "Execute" des Objektes. (TTimer geht also im Thread nicht !!!)
- nur im Mainthread darf auf GUI-Funktionalitäten (dazu gehört auch TTimer, leider ist nirgendwo sauber dokumentiert was als GUI-Funktionalität zu gelten hat) der FCL zugegriffen werden (tut man das in einem Thread stürzt das Programm ab !!!!))
- Ein Thread muss entweder so programmiert werden, dass er eine Aktion ausführt und sich dann beendet (aus Execute herausläuft), oder - wenn er als Dauerläufer in einer "Endlos"-Schleife arbeiten soll, er immer wieder auf eine Aktion kommt, die im Betriebssystem wartet (z.B. In Deinem Projekt im "blocking" Modus auf Zeichen aus der seriellen Schnittstelle wartet). Zur Not kann auch "sleep" helfen.
- mit "TThread.Synchronize" und "Application.QueuAsyncCall" (und den Windows-infizierten "Message"-Methoden) kann ein Thread ein Mainthread-Event auslösen, um z.B. GUI-Aktionen vom Mainthread ausführten zu lassen.
- Wenn man Speicher-Bereiche (Variablen) gemeinsam mit mehreren Thread (auch Mainthread) verwendet (z.B. zur Daten-Übergabe und Synchronisation), miss man diese gegen konkurrierende Zugriffe schützen. Man kann hier (z.B.) (für einzelne Zahlen) "Atomic" Funktionen verwenden (sehr schnell) oder (normal) mit vorgegebenen Objekten arbeiten (TThreadList) oder eigene Schutz-Mechanismen mit "TCriticalSection" einbauen.

In jedem Fall muss man beim Programmieren von Threads ziemlich aufpassen, damit man nichts falsch macht. (Beispiel: TList und TStringlist gelten als nicht Threadfest. Eine Instanz von TList oder TStringlist darf nicht von mehreren Thread verwendet werden, mehrere Threads dürfen allerdings durchaus jeweils unterschiedliche Instanzen von TList und TStringlist verwenden. Strings sind (soweit ich weiß) Threadfest implementiert, so dass mehrere Threads dieselben Strings verwenden können. ThreadList ist (natürlich) definitionsgemäß Threadfest.

Zu Deinem Problem:
Daten-Empfang von asynchronen Schnittstellen kann man eigentlich nur sinnvoll in einem Thread (mit Blocking Read) machen. (Dasselbe gilt für alle anderen Datenströme wie TCP/IP-Sockes, Pipes, ...)
Deshalb gibt es für Delphi mit "AsyncPro" ein (inzwischen kostenloses) Tool (nur für Windows), mit dem man beliebig viele Schnittstellen (Asynchron und TCP/IP), aufmachen kann und das die komplexe Thread-Technik im inneren versteckt. An das User-Programm werden Daten mittles Main-Thread-Events übergeben. So braucht der Anwender-Programmierung sich um die Threads überhaupt nicht kümmern.

Leider hat sich noch niemand die Mühe gemacht den (auf Sourceforge frei verfügbaren) Code nach Lazarus und Linux zu portieren :( . Soweit ich weiß gibt es auch nichts vergleichbares (zumindest kommt der Wunsch danach regelmäßig in diversen Lazarus-Foren immer wieder auf).

Hope this helps,
-Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: LNet mehrere Verbindungen

Beitrag von Socke »

mschnell hat geschrieben:Vermutlich brauchst Du mehrere Threads.

lNet verwendet nicht-blockierende Sockets. Im der Hauptanwendungsschleife wird dann überprüft, ob etwas angekommen ist und gegebenenfalls die Ereignisse ausgelöst. Mit Threads kann natürlich auch arbeiten, man muss dann nur im Thread die entsprechende Methode aufrufen, die diese Ereignisbehandlung anstößt.

Für den Anfang empfehle ich lNet mit einer GUI-Anwendung auszuprobieren.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: LNet mehrere Verbindungen

Beitrag von af0815 »

Bei deinem Beispiel fällt mir auf, das es nur ein FNet Objekt gibt, dem zweimal eine Adresse zugewiesen wird. Damit ist nur immer die letzte gültig.

Ich kann das Beispiel leider auf meinem iPad nicht nachvollziehen :D nachdem Lazarus dort noch immer ein kleines Problem hat.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: LNet mehrere Verbindungen

Beitrag von mschnell »

Socke hat geschrieben:
mschnell hat geschrieben:Vermutlich brauchst Du mehrere Threads.

lNet verwendet nicht-blockierende Sockets. Im der Hauptanwendungsschleife wird dann überprüft, ob etwas angekommen


Das erzeugt dann 100% CPU-Last (außer man baut irgendwo ein Sleep ein oder macht das Pollen in einem Timer-Event, was den Leistungsbedarf senkt aber wiederum die Latenz erhöht).

Ich finde es keine gute Idee mit Polling den Rechner zu blockieren

Socke hat geschrieben: ... man muss dann nur im Thread die entsprechende Methode aufrufen, die diese Ereignisbehandlung anstößt


Dann muss man aber mit einem blocking Read (oder einer blockierenden "Warte auf Zeichen" Funktion) arbeiten, sonst nützt der Thread nix.

-Michsel

NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: LNet mehrere Verbindungen

Beitrag von NoCee »

Hallo zusammen,

mir hat mein Problem jetzt keine Ruhe gelassen und ich hab mir die Aussage von af0815 das ich nur 1 FNet Objekt
in meinem Programm habe genauer angeschaut. Und das ist richtig. bzw. die Aussage ist richtig und in meinem Prog
ist das dann natürlich falsch.
Ich habe daraufhin ein zweites mal das Objekt auf meine Form geholt (als FNet2) und habe einfach mehr oder weniger
alles was mit dem ersten Objekt zu tun hat kopiert und mit ...2 umbenannt
TForm1.LTCPComponent1Accept gibts alse als TForm1.LTCPComponent2Accept noch mal.
So hab ich das mit allen Variablen und Prozeduren usw. gemacht.

Ich habs dann auf 1 PC getestet und es hat zumindest mit localhost funktioniert.
Getestet hab ich 2 Server und 2 Clients in jeweils einem Programm auf verschiedenen Ports.
Ich vermute mal, wenn ich das so weiter treiben würde, also z.B. 5 TLTCPComponents auf meine Form ziehen würde,
könnte ich vermutlich 5 Clients gleichzeitig auf verschiedene Ports connecten lassen.
Ob das so der Weisheit letzter Schluß ist, kann ich Anfänger nicht sagen, aber mir hilfts insoweit, als das ich
mein kleines Projekt weiter treiben kann. :D


Bsb.:

Code: Alles auswählen

procedure TForm1.ConnectButtonClick(Sender: TObject);
begin
  {if FNet1.Connect(EditIP.Text, StrToInt(EditPort1.Text)) then
    FIsServer := False; }

   FNet1.Connect(EditIP.Text, StrToInt(EditPort1.Text)); // Client 1 wird connectet
   FNet2.Connect(EditIP.Text, StrToInt(EditPort2.Text)); // Client 2 wird connectet
end;



Danke für die Diskussion
Gruß
NoCee
Zuletzt geändert von Lori am Mi 22. Aug 2012, 09:43, insgesamt 1-mal geändert.
Grund: Highlighter

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: [erledigt] LNet mehrere Verbindungen

Beitrag von hde »

@NoCee,
ich hab jetzt nicht den kompletten Thread gelesen, versteh aber so dein Problem nicht. Warum willst du zwei Server auf unterschiedlichen Ports laufen lassen? Es reicht doch in der Regel ein Server und es können sich so viele Clients andocken wie du willst? Und untereschiedliche Aufgaben löst man über den Paketinhalt. Auch die Clients können über den Server miteinander kommunizieren

Was seh ich da was falsch?

hde

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: [erledigt] LNet mehrere Verbindungen

Beitrag von mschnell »

hde hat geschrieben: Warum willst du zwei Server auf unterschiedlichen Ports laufen lassen?

Meinst Du mit "Server" "Listening Ports" ?

Wenn völlig unterschiedliche Funktionen realisiert werden sollen finde ich es absolut sinnvoll mehrere unabhängige Ports aufzumachen.

Wenn zwei Clients sich auf den selben Port verbinden realisiert das Betriebssystem das (im Normalfall) dadurch dass jeder Aufruf auf einen anderen technischen Port umgeleitet wird. Ein ordentliches Server-Programm muss dann für jeden dieser Ports einen Thread starten (z.B Indy macht das automatisch so).

Das macht die Sache aber sicher nicht einfacher (Außer man verwendet Indy, das ja eigentlich mit Lazarus funktionieren sollte).

-Michael

NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: [erledigt] LNet mehrere Verbindungen

Beitrag von NoCee »

Hallo,

nur noch für die Nachfrager zur Erklärung meines jetzt fertigen Projekts, das mittlerweile das tut was ich mir vorgestellt habe:

Ich habe 2 Maschinen mit jeweils einem integrierten Datenserver von denen ich nach einem connect einfach eine String bekomme.
Damit meine Software sich verbinden kann brauch ich da schon mal 2 Clients gleichzeitig.
Die Software nimmt die Strings entgegen bereitet sie geringfügig auf und verteilt diese dann an andere PCs auf dem
ein Terminalprogramm(client) Telnet oder bei uns meistens "Putty" läuft.
Mein Programm bietet jetzt die Möglichkeit sich auf die verschiedenen eigenen Server(Listening)ports zu connecten.
Ein Connect auf
Port 5000 liefert dann z.B. nur die Daten der Maschine 1
Port 5001 die von Maschine 2
Port 5003 beides zusammen usw.

Über die Portnummer kann ich also auswählen welche Daten ich haben will.
Wollen mehrere User den gleichen Serverport meines Progs benutzen, geht das auch. Das stellt LNet schon so zur Verfügung.
Das Ganze stellt also einen Datensammler/Verteiler dar mit dem man von jedem PC aus z.B. Fehlermeldungen anschauen kann
ohne hier jeweils eine eigene Software installieren zu müssen der die Daten filtert bzw. aufbereitet.


Gruß
NoCee

Antworten