AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Spielwiese - SocketTest

Spielwiese - SocketTest

Ein Thema von stahli · begonnen am 7. Okt 2016 · letzter Beitrag vom 24. Mär 2017
Antwort Antwort
Seite 2 von 4     12 34   
mjustin

Registriert seit: 14. Apr 2008
2.799 Beiträge
 
Delphi 2009 Professional
 
#11

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 11:45
Unter Windows kannst du mit einem IOCP Server durchaus auch tausende Verbindungen gleichzeitig offen halten.
Schade, dass in Delphi diese Möglichkeit noch nicht out of the Box unterstützt wird. Indy (und auch DataSnap) skalieren nicht besonders gut, bei mehreren Dutzend Connections auf einem Server wird es schon etwas knapp.

Von zwei Millionen simultanen Connections auf einem einzigen Linux Server berichtete WhatsApp bereits im Jahr 2012: 1 million is so 2011
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
Michael II
Online

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
570 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 13:44
Vielleicht gefallen dir auch die ICS Komponenten von F.Piette: http://www.overbyte.be/

Ich habe damit ein Spiel programmiert, bei welchem nur bei der Anmeldung in den Onlinespielraum die Server eine wichtige Rolle spielen. Danach sind möglichst alle Spiele mit allen anderen via möglichst schnelle Wege via tcp verbunden [also jedes Spiel ist dann ein wenig Server und jedes ein wenig Client]. Es klappt prima .

Viel Spass bei deinem Projekt.
Michael Gasser
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.199 Beiträge
 
Delphi 10.4 Sydney
 
#13

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 16:10
TCP Connections hält man bei solchen Anwendungsfällen eigentlich immer permanent offen. Unter Windows kannst du mit einem IOCP Server durchaus auch tausende Verbindungen gleichzeitig offen halten. Hierbei wird dann nicht pro eingehender Client Verbindung ein Thread erstellt, sondern ein Thread-Pool genutzt.
Vielleicht gefallen dir auch die ICS Komponenten von F.Piette: http://www.overbyte.be/

Das wären dann aber beides asynchrone non blocking Lösungen.


Zwischenzeitlich war ich der Meinung, dass die Indys vom Ansatz her sinnvoller wären. Sie arbeiten zwar blockierend aber die Kommunikation ist dafür klarer und nachvollziehbarer.
Was mich hier stört, ist die schlechtere Scalierbarkeit.
Es steht zwar aktuell nicht an, aber wenn es mal 1000 gleichzeitige Zugriffe auf einen Server gäbe, käme man mit den Indys halt (offenbar) in Probleme.


Insofern dachte ich mir, jetzt doch die Kommunikation asynchron abzuwickeln und diese selbst zu optimieren (also pro Client nicht mehrfach die selbe Information zu schicken und somit nicht massenweise Events anzuhäufen).

Eigentlich klingt das ganz gut (etwas mehr Aufwand aber auch mehr Leistung als bei den Indys) --- ABER --- ich würde die Events gern in eine eigene Warteschlange stellen und diese in einem eigenen Thread abarbeiten, also keine Windows-Messages erzeugen, sondern eigene in Form von Records oder Objekten.
Diese sollten in einer threadsaven Liste abgelegt werden (wenn sie vom Manger als relevant eingestuft werden) und dann in einem folgenden Schritt verarbeitet werden.
So könnte man z.B. folgendes lösen:
Alle Paar ms liefert der Server mir zur Anzeige meinen aktuellen Kontostand. Da dieser gerade erwartungsgemäß ansteigt 5..34..2345..194322... gibt es ständige Updates.
Da die Client-GUI gerade so schnell nicht hinterherkommt könnte der Manager die vorherige Konto-Info verwerfen und mit der neusten überschreiben. So hat die GUI dann nur eine Änderung darzustellen.
Sofern natürlich alle Änderungen relevant sind, könnte der Manager diese chronologisch sammeln.


Also das wäre meine bevorzugte Lösung -> non blocket sockets aber ohne an Windows(-Nachrichten) gebunden zu sein.
Aber so etwas gibt es nicht - oder?


...

ähh

...

halt

...

Ok, man könnte sich in der OnClientRead-Behandlung eine Liste von eigenen Nachrichten erzeugen...
Dann wäre es nur Aufgabe des Mainthreads, die Nachrichten für den Manager aufzubereiten, wo diese dann verarbeitet werden.

Aber damit wäre man immer noch auf Windows festgelegt und könnte nicht so einfach auf eine andere Plattform wechseln.



Also steht die Entscheidung wohl zwischen

1) Indy als einfache Lösung mit der Option anderer Plattformen, aber eingeschränkter Client-Anzahl

2) non blocket Sockets (oder ICS) als performantere Lösung mit mehr eigenem Verwaltungsaufwand aber Festlegung auf Windows


Ich bin weiterhin verwirrt und für Äußerungen dankbar.


EDIT:
Mein gewünschtes Modell wäre wohl so etwas wie ein IOCP-Server. Das schaue ich mir heute Abend nochmal genauer an. Aber wäre das auch auf anderen Plattformen umsetzbar?
UDP ist für mich kein Thema. Nachrichten müssen sicher ankommen.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (12. Okt 2016 um 16:30 Uhr)
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
2.799 Beiträge
 
Delphi 2009 Professional
 
#14

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 18:32
EDIT:
Mein gewünschtes Modell wäre wohl so etwas wie ein IOCP-Server. Das schaue ich mir heute Abend nochmal genauer an. Aber wäre das auch auf anderen Plattformen umsetzbar?
IOCP braucht man nicht, wenn viele Clients lediglich Nachrichten vom Server erhalten sollen:

Ein Serverprozess, der laufend Nachrichten erzeugt ---> (Sehr) viele Clients, die nur die Nachrichten erhalten sollen (via "Server Push")

Das geht plattformübergerifend mit einem Message Broker wie RabbitMQ:

Delphi Server ---> RabbitMQ --- Delphi Clients

clientseitig:
* alle Clients verbinden sich nur mit dem Message Broker. Das bedeutet je Client eine einzige Verbindung (z.B. Indy Sockets) zum RabbitMQ Server.
* die Clients 'abonnieren' nach dem Verbindungsaufbau einen benannten logischen Nachrichtenkanal beim RabbitMQ Server, dessen Nachrichten sie erhalten möchten
* der Client wartet auf Nachrichten

serverseitig:
* der Server baut eine einzige Verbindung zum Message Broker auf
* der Server sendet Nachrichten an den logischen Nachrichtenkanal auf dem Message Broker, falls welche gesendet werden sollen
* der Message Broker sendet diese Nachricht an alle Clients, die diesen Nachrichtenkanal abonniert haben

So wird erreicht, dass der Delphi Server nie mehr als eine Socket Verbindung benötigt.

Ob die Nachrichten an einem einzigen, tausend oder zehntausend Clients zugestellt werden, macht für den Delphi Prozess keinen Unterschied. Es laufen nicht für jeden Client separate Threads im Delphi Prozess.

Und das Beste: auch wenn zehntausend Clients gleichzeitig Nachrichten an den Delphi-Server senden wollen: der Delphi benötigt nur eine einzige Socket-Verbindung, zum RabbitMQ Server.

p.s. RabbitMQ ist natürlich nur ein Beispiel, es ginge ebenso mit einem ActiveMQ oder Artemis Message Broker (alle open source)
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
7.990 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 18:41
1) Bei mir arbeitet der Server oft deutlich (10-30 mal) langsamer als normal, wenn die Delphi-IDE geschlossen ist. Starte ich die IDE, läuft er wieder normal, schließe ich sie, ist er wieder langsamer. Das ist jedoch nicht immer so (im verlinkten Video z.B. nicht). Kann das jemand einordnen?
Wie ich gerade erst gelernt habe liegt das an timeBeginPeriod, das von Delphi benutzt wird um die minimale Timerauflösung herunterzusetzen. Dadurch kehrt Sleep schneller zurück, insbesondere, wenn Sleep(1) oder so benutzt wird.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.199 Beiträge
 
Delphi 10.4 Sydney
 
#16

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 20:02
@mjustin

Mein realer Anwendungsfall sieht eher so aus, dass die Clients sich Daten gezielt beim Server abholen, und zwar danach, was sie gerade anzeigen sollen.

Also der eine Client stellt die Kundenliste dar, und nach einem Pagewechsel jetzt den Fahrplan der DB.
Ein anderer Client zeigt ein Kochrezept an.

Sie sagen jeweils dem Server, was sie gerade brauchen, puffern das und stellen die Daten dar.

Ein anderer Client Ändert jetzt irgend etwas in der Datenschicht. Z.B. wird ein Kunde hinzugefügt.

Derzeit ändert (in meinem Realprojekt, nicht in der Demo hier) der Server einen Zeitstempel auf Now.
Die Client fragen regelmäßig, den aktuellen Serverzeitstempel ab.
Wenn der jetzt neuer ist als bei der letzten Abfrage holen sie sich die o.g. Daten (bzw. die, die sie gerade darstellen) neu vom Server ab und zeichnen die GUI neu. Das heißt, einen Moment werden noch die Daten aus dem Puffer angezeigt (oder wenn nicht vorhanden leere Controls oder Zellen) und nach der Aktualisierung umgehend die neuen Daten.

Da das als lazy loading abläuft gibt es ein paar kurze Verzögerungen, die ich noch etwas optimieren wollte.


Das heißt, dass die Clients sich im Regelfall schon ganz bestimmte Informationen abrufen müssen.
Ein automatischer Rundruf vom Server könnte sich eigentlich auf ein "Es gibt neue Daten!" beschränken.


Insofern war die Demo hier etwas missverständlich zu meiner echten Zielstellung. Ich wollte hier nur mal den Server testweise extrem beschäftigen
... und habe festgestellt, dass dies nicht so funktioniert wie ich erwartet hatte.


So wie ich Message Broker inzwischen verstanden habe wären die für meine reale Zielstellung eher nicht hilfreich (da die Clients ja direkt bestimmte Daten nach ihren individuellen Bedürfnissen abfordern bzw. gezielte Änderungen an bestimmten Daten initiieren).




@jaenicke
Ok, danke!



EDIT: Idee ... Oh Ich versuche da mal was. Kann ein paar Tage dauern...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (12. Okt 2016 um 20:25 Uhr)
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
2.799 Beiträge
 
Delphi 2009 Professional
 
#17

AW: Spielwiese - SocketTest

  Alt 12. Okt 2016, 20:29
So wie ich Message Broker inzwischen verstanden habe wären die für meine reale Zielstellung eher nicht hilfreich (da die Clients ja direkt bestimmte Daten nach ihren individuellen Bedürfnissen abfordern bzw. gezielte Änderungen an bestimmten Daten initiieren).
Tja, ich habe ja noch nicht alle Möglichkeiten der Message Broker dargestellt, um keinen Informations-Overkill zu bewirken

Die meisten Message Broker unterstützen auch Kommunikation in der Art eines Remote Procedure Calls (RPC). Dazu erzeugt jeder Client einen individuellen, nur für ihn gültigen Nachrichtenkanal auf dem Server (der beim Verbindungsende gelöscht wird). Dann sendet der Client seine spezielle Message an einen Nachrichtenkanal (zum Beispiel: "ich brauche das Rezept für Boeuf Stroganoff"). Und innerhalb dieser Nachricht gibt der Client an, dass er die Antwort auf seinem individuellen Kanal erwartet. Der Message Broker leitet die Nachricht an den Delphi Server weiter, schlägt das Rezept nach, und sendet es los.

So kann ein Message Broker individuelle Anfragen der Clients an den Delphi Server weiterleiten, und die Antworten an den richtigen Client zurück senden.

Dabei bleibt der große Vorteil des Message Brokers erhalten, dass der Delphi Server nur eine einzige Socket-Verbindung zu Message Broker aufbaut. Unabhängig von der Zahl der Clients, deren RPC Requests er beantwortet.
Michael Justin
habarisoft.com
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.199 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: Spielwiese - SocketTest

  Alt 24. Okt 2016, 16:20
Also das wäre meine bevorzugte Lösung -> non blocket sockets aber ohne an Windows(-Nachrichten) gebunden zu sein.
Aber so etwas gibt es nicht - oder?
...
ähh
...
halt
...
Ok, man könnte sich in der OnClientRead-Behandlung eine Liste von eigenen Nachrichten erzeugen...
Dann wäre es nur Aufgabe des Mainthreads, die Nachrichten für den Manager aufzubereiten, wo diese dann verarbeitet werden.
In dem Sinne habe ich jetzt etwas realisiert und muss noch ein paar Details fertig stellen und testen.

Im Grunde gibt es mehrere Module (Interfaces), die miteinander verbunden - aber auch austauschbar - sind.
Die Businesslogik und die GUI-Logik können IMessages für die Gegenseite erstellen und diese ihrem Handler übergeben.
Der Handler entscheidet, wann er die Message wirklich versendet und übernimmt das gesamte Protokoll.
Ebenso zerlegen die Handler beim Empfang von Nachrichten die (verbunden)Pakete in einzelne Häppchen, fordern sich von der Businesslogik bzw. GUI-Logik (bzw. von deren MessageResolvern) entsprechende MessageInterfaces ab und entscheiden wiederum selbstständig, wann sie diese Messages tatsächlich zur Verarbeitung weiter geben.

Man kann Messages eine Priorität zuweisen oder den Status Singleton oder einen Timerwert.
Messages mit Priotät werden in der Messagequeue vorn eingefügt.
Singletons werden, falls sich schon eine gleichartige Message in der Queue befindet, durch die neue Message überschrieben (so lange die alte halt noch nicht verarbeitet wurde).
Timerwerte bewirken, dass Nachrichten dieser Identität frühestens n ms nach dem letzten Versand verschickt bzw. verarbeitet werden.

So kann man durch die Einstellung der IMessage-Eigenschaften den Handlern direkt vorgeben, wie sie den Versand optimieren sollen.

In der Buinesslogik und GUI-Logik muss man nur noch die Messages erzeugen, aus erhaltenen StringListen wieder parsen und in der Logik verarbeiten.


Die Handler nutzen ihrerseits Module für die tatsächliche Datenübertragung (aktuell bei mir mit non blocking sockets).
Diese Module könnte man grundsätzlich auch austauschen, so dass man auch z.B. Indys nutzen könnte, ohne die Business- oder GUI-Logik ändern zu müssen.

Besteht Interesse an der Lösung?
Dann würde ich nochmal ein Video erstellen und das Projekt hier einstellen.

Bis hierher sieht das gut aus. Ein paar Tage brauche ich dann aber noch für den Rest.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (24. Okt 2016 um 16:55 Uhr)
  Mit Zitat antworten Zitat
einbeliebigername

Registriert seit: 24. Aug 2004
130 Beiträge
 
Delphi XE8 Professional
 
#19

AW: Spielwiese - SocketTest

  Alt 24. Okt 2016, 17:47
Hallo Stahli,

natürlich besteht da Interesse. Dein Video war schon beeindruckend. Habe leider aktuel wenig Zeit, sonst hätte ich das mal selbst ausprobiert.
Mit freundlichen Grüßen, einbeliebigername.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.199 Beiträge
 
Delphi 10.4 Sydney
 
#20

AW: Spielwiese - SocketTest

  Alt 24. Okt 2016, 18:04
Ja super, dann mache ich das mal die nächsten Tage fertig.

Das Problem an meiner ersten Lösung war, dass dort nur immer die erste von mehreren verbundenen Nachrichten verarbeitet wurde und die Geschäftslogik sich mit den Texten herumschlagen musste.

Kamen beim Client z.B. erst

command1
command2
command3

und dann

command2
command1
command3

an, wurde jeweils nur die erste Nachricht geparst und der Rest ignoriert - bis ich dann diese Verkettung der Nachrichten erkannt habe.

Das lösen jetzt meine Handler automatisch auf, wandeln die Textnachrichten in IMessages um, die auch die Geschäftslogik verarbeiten kann und geben diese kontrolliert zur Weiterverarbeitung raus.
Die einzelnen Aufgaben werden in einzelnen Threads abgearbeitet und die Nachrichten werden in threadsicheren (hoffentlich) Queues gepuffert.

So muss die Geschäfts- und GUI-Logik jetzt nur noch IMessages erstellen und verarbeiten und man muss sich um den Nachrichtenfluss nicht mehr selbst kümmern.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 18:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf