Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Server/Client kleine Pakete sehr oft an mehrere Clienten (https://www.delphipraxis.net/191346-server-client-kleine-pakete-sehr-oft-mehrere-clienten.html)

sonny2007 4. Jan 2017 19:03

Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Hiho Zusammen,

ich habe ein Problem mit dem Datenaustausch zwischen mehreren Clienten über einen Server.

Folgendes Szenario

Client 1, Client 2, Client 3
| | |
Server TCP Indy

Jeder Client sendet alle 100-200ms ein Buffer oder Stream von ca 0,2-0,6KByte.

Diese sollen dann vom Server an alle anderen Clienten verteilt werden.

Welcher Lösungsansatz ist der Richtige?
ist TCP die richtige Wahl ?

Folgendes habe ich bisher probiert.
per Stream

Delphi-Quellcode:
....

    ms := TMemoryStream.Create;
    Try
      ms.Write(tmpClient, SizeOf(tmpClient));
      if (SendStream(IdClient, TStream(ms)) = False) then
        Exit;
    Finally
      ms.Free;
    End;

    ms := TMemoryStream.Create;
    Try
      if (ReceiveStream(IdClient, TStream(ms)) = False) then
        Exit;

      //slServerLog.Add('Receive StreamSize ' + IntToStr(ms.Size));
      SetLength(arClients, ms.Size div SizeOf(arClients[0]));
      // Setzen der Anzahl der Elemente im Array
      ms.Position := 0;
      for i := 0 to High(arClients) do
        ms.Read(arClients[i], SizeOf(arClients[i]));
    finally
      ms.Free;
    end;
per Buffer mit Protokoll, was jedoch extrem langsam ist. Habe das Gefühl das es sich eher für Messenger eignet.
Kann aber auch an meiner Unwissenheit liegen.

Grüße
sOn

stahli 4. Jan 2017 20:11

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Es ist besser, wenige größere Pakete zu übertragen als extrem viele kleine.
Ich stand mal bei dem gleichen Problem: http://www.delphipraxis.net/180134-i...ptimieren.html
Also wenn Du einige Daten puffern und dann übertragen kannst würde das sicher helfen.

Indy arbeitet nur blockierend. Client fragt und Server antwortet.
Wenn der Server alle Clients versorgen soll müssen die Clients ständig nachfragen (polling / long polling).



Ich habe jetzt mal Versuche mit asynchroner Kommunikation unternommen und finde das sehr empfehlenswert.
http://www.delphipraxis.net/190482-s...ockettest.html
Mit Hilfe des Frameworks ist die Kommunikation sehr übersichtlich.
Man versendet einfach Nachrichten (Interfaces), die auf der Gegenseite automatisch wiederhergestellt werden und dann nur noch in die Logik übernommen werden müssen.



Es gibt noch alternative Lösungen für die Kommunikation zwischen mehreren Partnern. Dazu kann ich aber nichts genaueres sagen.

Mavarik 5. Jan 2017 02:59

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von sonny2007 (Beitrag 1358099)
Jeder Client sendet alle 100-200ms ein Buffer oder Stream von ca 0,2-0,6KByte.

Diese sollen dann vom Server an alle anderen Clienten verteilt werden.

Welcher Lösungsansatz ist der Richtige?
ist TCP die richtige Wahl ?

Also... UDP Ist ein bisschen schlanker, dafür ist nicht sichergestellt ob und in welcher Reihenfolge die Pakete ankommen.

TCP/IP ist schon ok... ein Frame ist aber ca 1500 bytes lang inkl. 20 Byte Headerdaten. Und noch das ein oder andere Byte... also Deine 200 oder 600 byte sind kein Thema.

Ein Server spaltet normalerweise für jeden Client einen eigenen Thread ab. Wenn Du die Daten verteilst, Musst Du dem Buffer also so lange im Speicher halten, bis "TimeOut" oder alles Clients Ihn empfangen haben. So sparst Du Dir ne Kopie für jeden Client. (RefCounted Queued- oder Ring-Buffer).

Von diesen Paketen solltest Du im lokalen Netz "physikalisch" ca. 65.000 Stk. pro Sekunde verteilen können.
Bei einer Client Anzahl unter 1000 sollte es also klein Problem sein... :stupid:
Wo bei Du sicherlich nicht 1000 Threads aufmachen willst... :stupid:

aber bei 5-10x pro Sekunde 500 Bytes zu übertragen... an sagen wir mal 10 Clients... kein Thema...

Oder habe ich mich verrechnet? Ist schon spät... 8-)

Mavarik

mjustin 5. Jan 2017 07:29

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von stahli (Beitrag 1358108)

Indy arbeitet nur blockierend. Client fragt und Server antwortet.
Wenn der Server alle Clients versorgen soll müssen die Clients ständig nachfragen (polling / long polling).

Wenn der Server alle Clients versorgen soll, sendet der Server einfach an alle Clients.
Das geht mit allen Socketverbindungen, Indy ist da keine Ausnahme :)

Sockets sind, sobald einmal die Verbindung hergestellt wurde, bidirektional.

Blockierend und Request/Reply sind zwei verschiedene Paar Schuhe. Wenn der Server an Clients sendet, wird bei Indy die Servernachricht blockierend gelesen. Normalerweise in einem Thread, der im Hintergrund läuft.

Beispiel für Message Push:

https://mikejustin.wordpress.com/201...-push-example/

stahli 5. Jan 2017 10:11

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Da ist man der Meinung, man hätte alles Wesentliche so halbwegs verstanden und dann so was... :oops:

Na gut, mit den asynchronen Sockets komme ich zunächst erst mal wunderbar zurecht, wenn sich da nicht irgendwann doch nochmal Probleme auftun...

BrightAngel 5. Jan 2017 11:52

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Ich finde, wir haben noch zu wenig Informationen vom TE oder?

Ganz konkret gibt es verschiedene Ziele für die man Client/Server Software schreibt:
  • Ist es wichtig, dass die Nachrichten von allen Clients zeitnah ankommen (Puffern vs direkt senden)
  • Ist es wichtig, dass die Nachrichten überhaupt ankommen (einfaches Notify vs wichtiger Datentransport)
  • Werden einzelne Clients untereinander identifiziert? Dürfen Nachrichten verschiedener Clients vom Server zusammengefasst werden? (so wie ich das verstanden habe, soll dass ja ein All-to-all Informationsfluss werden, oder?)
  • Ab wann ist ein Client Teil der zu informierenden Clientenmenge (falls TCP: was passiert bei Verbindungsabbruch)
  • Wo befindet sich das Setup? Lokales geschütztes Netz vs großes, böses Internet?
  • Falls großes böses Internet: Wie sensibel sind die Daten? Sollte man die vielleicht noch TLS tunneln...

Also vielleicht regen diese Punkte noch den weiteren Informationsfluss hier an :)

Brighty

Namenloser 5. Jan 2017 11:55

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Kurze Anmerkung zu mjustin und stahli: Man kann natürlich auch vom Server aus blockierend in den Socket schreiben, ohne dass es vorher eine Anfrage des Clients gegeben haben muss. Allerdings kann dann halt bei Indy, während geschrieben oder sonstwie blockiert wird (vgl. sleep() im Beispiel), keine Nachrichten des Clients empfangen. Prinzipiell geht das zwar mit Sockets mithilfe eines zweiten Threads, aber nicht mit Indy, weil Indy nicht threadsafe ist. Auch die anderen mir bekannten Libs für Delphi bzw. FreePascal haben dieses Problem.

mjustin 5. Jan 2017 12:45

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von Namenloser (Beitrag 1358163)
nicht mit Indy, weil Indy nicht threadsafe ist

Welche Delphi Version - eins? :)

scrat1979 5. Jan 2017 13:11

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Ich verwende für den Datentransfer über das Netzwerk die Komponenten von ESEGECE. Sehr einfach zu bedienen, für das private Umfeld kostenlos und selbst der Source nicht besonders teuer. Threadsafe, auf den Indys aufbauend, ich bastel mir damit gerade meine eigenen Server und Client-Komponenten. Vielleicht willst du dir das mal ansehen... das waren die einzigen Komponenten, welche es mir EINFACH erlaubten mit dem Netzwerktransfer zurechtzukommen.

Mavarik 5. Jan 2017 14:12

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Richtig gut im threading sind die ICS
Damit kann man ganz schnell einen Client / Server Lösung bauen.

sonny2007 5. Jan 2017 14:49

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Hi,

danke erstmal für die vielen Antworten.

Zitat:

Zitat von BrightAngel (Beitrag 1358162)
[*]Ist es wichtig, dass die Nachrichten von allen Clients zeitnah ankommen (Puffern vs direkt senden)
Brighty

- Ja ist es. wie bei einem online Spiel. Du verursachst einen Wert bspw. Schaden, Heal, bewegst dich etc ...

Zitat:

Zitat von BrightAngel (Beitrag 1358162)
[*]Ist es wichtig, dass die Nachrichten überhaupt ankommen (einfaches Notify vs wichtiger Datentransport)
Brighty

-Ja wieso nicht :)

Zitat:

Zitat von BrightAngel (Beitrag 1358162)
[*]Werden einzelne Clients untereinander identifiziert? Dürfen Nachrichten verschiedener Clients vom Server zusammengefasst werden? (so wie ich das verstanden habe, soll dass ja ein All-to-all Informationsfluss werden, oder?)
Brighty

- Also Client sendet bspw. den Schadenswert an Server und alle anderen Clienten erhalten diesen Wert sofort um Rückschlüsse zu ziehen, wieviel Schaden jeder einzelne Spieler macht. Wenn da ein Zeitversatz durch Puffern von 2sec gäbe währe das nicht so toll.

Zitat:

Zitat von BrightAngel (Beitrag 1358162)
[*]Wo befindet sich das Setup? Lokales geschütztes Netz vs großes, böses Internet?
Brighty

- ES soll über das große böse Internet laufen :)


Zitat:

Zitat von BrightAngel (Beitrag 1358162)
[*]Falls großes böses Internet: Wie sensibel sind die Daten? Sollte man die vielleicht noch TLS tunneln...
Brighty

- völlig irrelevant. Da nur Schadenswerte übertragen werden


Aktuell hat jeder Client einen ListenerThread laufen der die Message empfängt und diese verarbeitet.
Der Server empfängt die der Daten und sendet sie sofort wieder an alle Clienten.

Doch das wird bei 10 User schon sehr fehleranfällig. Vermutlich weil ich es auch nicht richtig umgesetzt habe.
Daher ja meine Frage, welcher Lösungsansatz bietet sich hier an.

Client 1 --- verursacht 1000 Schaden
Client 2 --- verursacht 500 Schaden

jetzt bekommt der Server in 2 Datenpakete die er in 2 seperaten Threads verwaltet.
ist puffern in dem Fall sinnvoll ?
Oder einfach in dem gleichen Thread wieder an alle Clienten senden?

was passiert wenn am client 1 Paket eintrifft und er gerade ein vorheriges verarbeitet ?

Benutzt wird übrigens Delphi 10.1 (Studentenpreis sei dank ;)

Grüße
sOn

Namenloser 5. Jan 2017 15:45

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von mjustin (Beitrag 1358169)
Zitat:

Zitat von Namenloser (Beitrag 1358163)
nicht mit Indy, weil Indy nicht threadsafe ist

Welche Delphi Version - eins? :)

Moment. Indy verwendet zwar Threads, das heißt aber nicht automatisch, dass die Komponenten selbst threadsafe sind. Es ist bei Indy meines Wissens nicht möglich, eine Komponente aus mehreren Threads heraus gleichzeitig zu verwenden. Also z.B. gleichzeitig in Thread A ein Receive auszuführen und in Thread B ein Send – auf dem gleichen Socket.

mjustin 5. Jan 2017 15:52

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von Namenloser (Beitrag 1358163)
Kurze Anmerkung zu mjustin und stahli: Man kann natürlich auch vom Server aus blockierend in den Socket schreiben, ohne dass es vorher eine Anfrage des Clients gegeben haben muss. Allerdings kann dann halt bei Indy, während geschrieben oder sonstwie blockiert wird (vgl. sleep() im Beispiel), keine Nachrichten des Clients empfangen. Prinzipiell geht das zwar mit Sockets mithilfe eines zweiten Threads, aber nicht mit Indy, weil Indy nicht threadsafe ist.

Bei Indy besteht Thread Safety nicht für den Fall, dass aus einem zweiten Thread gleichzeitig aus dem Socket zu lesen oder zu schreiben, während dort bereits ein anderer Thread liest oder schreibt.

Jedoch ist bei Indy problemlos möglich, auf den Socket aus einem Thread zu lesen, und auf denselben Socket aus einem anderen Thread heraus zu schreiben. Eine Socketconnection, zwei Threads (einer liest Daten, einer sendet Daten).

Beispiel: TIdTelnet, über die Telnet-Serververbindung sendet der Client Daten auf den Socket, während der Client in einem separaten Thread Nachrichten vom Server empfängt. Ein Socket, eine in TIdTelnet enthaltene TIdTCPConnection-Instanz, zwei Threads.

Das ist threadsafe.

Namenloser 5. Jan 2017 16:27

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von mjustin (Beitrag 1358184)
Jedoch ist bei Indy problemlos möglich, auf den Socket aus einem Thread zu lesen, und auf denselben Socket aus einem anderen Thread heraus zu schreiben. Eine Socketconnection, zwei Threads (einer liest Daten, einer sendet Daten).

Ist das denn irgendwo dokumentiert? Ich habe dazu nie was gefunden.

BrightAngel 5. Jan 2017 22:15

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Okay. Ich versuch mal zu sortieren :)

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
wie bei einem online Spiel. Du verursachst einen Wert bspw. Schaden, Heal, bewegst dich etc ...

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
ES soll über das große böse Internet laufen :)

Die Sache ist die: UDP kommt nicht mehr überall durch alle Middleboxen der Netzwerke unverändert durch und kommt eben auch nicht zuverlässig an, aber es hat auch den praktischen Vorteil, dass es keinen initialen "Verbindungsaufbau" wie TCP am Anfang hat. Zudem verhält sich UDP unfair gegenüber TCP auf der Leitung, welches seine Geschwindigkeit selbst regelt (self clocking durch ACKs z.B.).

Bei TCP gibt es auch den Vorteil, dass alle Pakete garantiert in der selben Reihenfolge auf der Anwendungsebene des Empfängers (d.h. bei dir am Socket) eintreffen, wie sie beim Sender losgeschickt wurden. Ich unterstelle dir einfach mal diese Intension.

Ich glaube, ich würde zu TCP in diesem Fall tendieren; aus dem Grund, da du ja geschrieben hattest, dass kontinuierlich Daten für die Übertragung anfallen. Damit das dann aber auch funktioniert, würde ich versuchen "langlebige TCP-Verbindungen" zu benutzen (das heißt, dass du nicht jedes Mal wegen einer Nachricht dich zum Server connectest, sondern das selbe Socket so lange wie möglich versuchst zu verwenden...). Hintergrund: TCP fängt erst langsam an die Übertragungsrate hochzudrehen. Das heißt aber auch, dass die Verbindung kontinuierlich verwendet werden sollte (in vielen Protokollen das so genannte keep-alive oder heartbeat). Da bei dir scheinbar immer Daten anfallen, scheint das also die Beste Wahl dafür zu sein.

Allgemein sollte man bei Netzwerk (noch mehr als bei normaler FileIO) immer damit rechnen, dass was schiefgehen kann (Verbindung ist kaputt gegangen; Puffer der Betriebssytems ist voll; ...) und man da "graceful recovered" (Neue Verbindung aufbaut/erwartet; Auf das Betriebssytem und die Hardware wartet; ...).

Warum ich in meiner initialen Liste gefragt hatte, ab wann ein Client zu der Menge der zu informierenden Nachrichtenempfänger gehören soll: Was machst du, wenn ein Client grade "nur kurz" keine Verbindung hat?
Das Problem: Du weißt wenn eine Verbindung zusammenbricht nicht, ob das System nur kurz weg ist und gleich wieder eine neue Verbindung aufbauen wird, die die alte Verbindung ersetzt (das Programm aber weitergelaufen ist; also insbesondere der Programmzustand auf dem Zielsystem noch intakt ist!) oder ob das Programm grade (z.B. durch einen fatalen Fehler) sterben gegangen ist. Was passiert also mit den Nachrichten derjenigen Clients, die seit dem Verbindungsabbruch Nachrichten zum Server gesendet hatten? Hälst du die vor? Wenn ja, wie lange?


Zitat:

Zitat von sonny2007 (Beitrag 1358174)
Also Client sendet bspw. den Schadenswert an Server und alle anderen Clienten erhalten diesen Wert sofort um Rückschlüsse zu ziehen, wieviel Schaden jeder einzelne Spieler macht. Wenn da ein Zeitversatz durch Puffern von 2sec gäbe währe das nicht so toll.

Soweit klar. Aber es ist ja (soweit ich das richtig verstanden habe) so, dass alle Clients gleichzeitig immer Nachrichten senden. Dann kommen ja auch mehrere Nachrichten von verschiedenen Clients (fast) gleichzeitig an. Diese könntest du beim Verteilen zu den Clients zusammenfassen.
Beispiel: Clients A, B und C sind zu Server S verbunden. A und B senden Nachrichten, die zeitgleich bei S eintreffen. Beim Verteilen an A sendet S die Nachricht von B und zu B die Nachricht von A. Interessant ist dann aber C. C bekommt beide Nachrichten von A und B direkt in einem Paket.

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
Da nur Schadenswerte übertragen werden

... die du vmtl auf dem Server ohnehin validieren musst. Oft ist es sinnvoll nicht das Effektorische über die Leitung zu schicken (in dem Fall der Schaden), sondern das Aktuatorische (in dem Fall die Handlung, die zu einem Schaden führen wird; der Server würde dann die "Handlungsinformation" prüfen und in eine "Schadensinformation" umwandeln und diese dann senden) (Anmerkung: Das ist nur eine Anregung; vlt nicht direkt eine Antwort auf deine Frage... :oops:)

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
Aktuell hat jeder Client einen ListenerThread laufen der die Message empfängt und diese verarbeitet.
Der Server empfängt die der Daten und sendet sie sofort wieder an alle Clienten.

Doch das wird bei 10 User schon sehr fehleranfällig. Vermutlich weil ich es auch nicht richtig umgesetzt habe.
Daher ja meine Frage, welcher Lösungsansatz bietet sich hier an.

Ich vermute, dass du dann beim Verteilen mit dem Empfängerthread eines Clients direkt auf den anderen Sockets senden willst: Das ist das was die anderen hier als das "Thread-Problem" diskutiert hatten.
Wenn du nur unter Windows bist und keine Angst hast direkt die Windows API zu verwenden, kann ich dir auch IO Completion Ports empfehlen. Der Vorteil hier ist, dass du sogar nur einen Thread brauchst, um mehrere Clients zu bedienen (die grobe Idee: man wartet auf mehrere Sockets gleichzeitig)

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
jetzt bekommt der Server in 2 Datenpakete die er in 2 seperaten Threads verwaltet.
ist puffern in dem Fall sinnvoll ?
Oder einfach in dem gleichen Thread wieder an alle Clienten senden?

Das geht auch. Entweder kannst du es z.B. mit dem Mailbox Entwurfsmuster versuchen (das quasi jedem Socket einen Thread überlässt und dann halt Nachrichten zwischen den Threads effizient hin und herschickt), oder s.o. IO Completion Ports; oder es gibt auch Bibliotheken, wie zum Beispiel das platformunabhängige libevent, das gleich ein ganzes Eventsystem bereitstellt (Anmerkung: das letzte habe ich noch nicht in delphi verwendet, aber das sollte eigentlich trotzdem benutzbar sein...)

Zitat:

Zitat von sonny2007 (Beitrag 1358174)
was passiert wenn am client 1 Paket eintrifft und er gerade ein vorheriges verarbeitet ?

Das Betriebssytem puffert intern ohnehin für jedes Socket. Also zwischen zwei "reads" geht im Allgemeinen nichts verloren. Also wenn du zwischendurch was verarbeitest ist das okay (wenns dann halt sehr lange geht, dann denkt die Gegenseite, dass du nicht mehr da bist, also das ist ungut... -> Timeout).

Hoffe ich konnte mehr helfen, als verwirren :oops:

Brighty

Mavarik 6. Jan 2017 01:31

AW: Server/Client kleine Pakete sehr oft an mehrere Clienten
 
Zitat:

Zitat von sonny2007 (Beitrag 1358174)
Doch das wird bei 10 User schon sehr fehleranfällig. Vermutlich weil ich es auch nicht richtig umgesetzt habe.
Daher ja meine Frage, welcher Lösungsansatz bietet sich hier an.

Client 1 --- verursacht 1000 Schaden
Client 2 --- verursacht 500 Schaden

jetzt bekommt der Server in 2 Datenpakete die er in 2 seperaten Threads verwaltet.
ist puffern in dem Fall sinnvoll ?
Oder einfach in dem gleichen Thread wieder an alle Clienten senden?

Du must eine TimeSlice einführen. Ping Laufzeiten im Internet nicht vergessen...

Wenn 100 Spieler im Game sind... Sehen sich alle Spieler? Oder sind vielleicht 50 Spieler in einem anderen Raum.

Also kann der Server schon mal vor sortieren.

Wenn von 10 Spielern Schaden auf Spieler A gemacht wird dann reicht hierfür eine zusammengefasste Übertragung.
Wenn ich richtig liege dauert die Übertragung von 20 Byte genau so lange wie die von 1400 Byte... (Nie getestet aber so müsste es sein). Als bei angestrebten 60/FPS hast Du sagen wir mal 16 MS pro Frame zur Berechnung Du wirst aber nicht 60x pro Sekunde, Schaden berechne wollen/können aber vielleicht wie geschrieben 5x bei 1000ms hast Du also deine angegebenen 200ms Zeit um für Client A von N-Clients den schaden zu sammeln und falls nötig alle 200ms einmal ein Datenframe übertragen. Da die Übertragung im lokalen netz < 1ms für ein Paket ist - kein Thema. Bei einem Ping von 200 wird es schon knapp.

Waiting threads brauchen "keine" CPU. Also kannst Du dir einen "Haufen" worker Threads bauen. die alle nix machen außer bei einem TimeOut ein Heardbeat senden. Sonst warten die nur auf einen Pointer und einen SetEvent. So ein Thread starten in wenigen nano-Sekunden. (Oder waren es sogar nur Pico-Sekunden) Egal... SOFORT.

Jetzt noch die TimeSlices asynchron bauen...

Beispiel:

Bei MS startet:
0 Client A (Ping 20);
20 Client B (Ping 50);
70 Client C (Ping 100);
170 Client D
usw.

ggf. Kann durch geschicktes Rechnen die Zeiten noch am Ping besser angepasst werden.

Von diesen Steuer-Threads kannst Du natürlich mehr als einen haben. Und ggf. noch einen kleinen Random Wert drauflegen. Wenn bei einem MS-Counter von 1ms der Counter bei 70 an kommt, werden die Schadenswerte an Client C übertragen und er wird wieder vorgemerkt für Counter 270.

Usw..

Mavarik


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:42 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