Einzelnen Beitrag anzeigen

BrightAngel

Registriert seit: 13. Mär 2007
130 Beiträge
 
#15

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

  Alt 5. Jan 2017, 23:15
Okay. Ich versuch mal zu sortieren

wie bei einem online Spiel. Du verursachst einen Wert bspw. Schaden, Heal, bewegst dich etc ...
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?


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.

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... )

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)

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...)

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

Brighty
Do you have the email of god??? --- I have to tell him that I'm happy to be born!

Geändert von BrightAngel ( 5. Jan 2017 um 23:43 Uhr)
  Mit Zitat antworten Zitat