Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

41

21.03.2013, 09:51

Naja sie bekommt ein SocketSet und einen Timeout. Nach dem Timeout gibt sie an, ob Aktivität auf dem Socket ist oder nicht. Will ich Lesen und dabei warten bis Daten da sind, verwende ich direkt SDLNet_TCP_Recv; lagere ich die Überprüfung vor, lese ich schließlich auch mit der Funktion, nur blockiert zwingend sie nicht weil ja prinzipiell Aktivität vorliegt.
Nein. Die Funktion wartet, bis etwas auf dem Socket ankommt oder bis der Timeout erreicht ist, je nachdem, was früher eintritt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

42

21.03.2013, 10:11

Nein. Die Funktion wartet, bis etwas auf dem Socket ankommt oder bis der Timeout erreicht ist, je nachdem, was früher eintritt.


Okay, wenn du das so genau weißt, dann ist ja alles in Ordnung :)

Ist der Ansatz mit der Thread-Aufteilung so vertretbar? Hier nochmal was ich da gepostet hatte:

Server: Accept-/ Receive-Thread

Quellcode

1
2
3
4
5
6
7
8
solange server online:
    wenn aktivität auf listener socket:
        nimm neuen client an
    für jeden worker socket:
        solange aktivität:
            lies event
            gib event an in-queue
    delay


Server: Send-Thread

Quellcode

1
2
3
4
5
6
7
solange server online:
    nimm event von out-queue
    solange event leer:
        delay
        nimm event von out-queue
    ermittle ziel des events (worker)
    sende event an worker


Client: Send-/ Receive-Thread

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
solange client online
    // senden bis nichts mehr zu senden
    solange trve:
        nimm event von out-queue
        wenn event leer:
            break
        sende event an server
    // empfangen bis nichts mehr zu empfangen
    solange aktivität auf socket:
        empfange event
        gib event an in-queue
    delay


LG Glocke

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

43

21.03.2013, 10:16

1) Wieso sollte der Accept-Thread irgendwas anderes machen als Accept? Receive-Thread für Server über select() oder das SDL-Äquivalent.

2) Server Send-Thread sieht ok aus - außer vielleicht Nagle-Ack.

3) Client Send/Receive-Thread ist nicht gut. Blockiert sich gegenseitig. Receive und Send sollten unabhängig voneinander sein. Nicht pro Client einen Thread, sondern einen pro Aufgabe (Aufgabe = Send ODER Receive).
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

44

21.03.2013, 10:26

1) Wieso sollte der Accept-Thread irgendwas anderes machen als Accept? Receive-Thread für Server über select() oder das SDL-Äquivalent.


Ich arbeite komplett mit den SDL-Funktionen. Was meinst du mit "Wieso sollte der Accept-Thread irgendwas anderes machen als Accept?"? Meine Idee war, das Accepten (ist non-blocking) mit in den Receive-Loop einzubauen. So oft kommen keine neuen Clients dazu - von daher würde ich ggf. auf einen extra Accept-Thread verzichten wollen.

2) Server Send-Thread sieht ok aus - außer vielleicht Nagle-Ack.


Was meinst du damit genau?

/EDIT: Ich weiß jetzt nicht ob ich's erwähnt hatte: meine Queues sind non-blocking und geben den Zeiger auf die Daten (diese Queues speichern nur Zeiger) oder NULL zurück.

3) Client Send/Receive-Thread ist nicht gut. Blockiert sich gegenseitig. Receive und Send sollten unabhängig voneinander sein. Nicht pro Client einen Thread, sondern einen pro Aufgabe (Aufgabe = Send ODER Receive).


Also ein Send-Thread und ein Recv-Thread am Client?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

45

21.03.2013, 12:05

1) Wieso sollte der Accept-Thread irgendwas anderes machen als Accept? Receive-Thread für Server über select() oder das SDL-Äquivalent.


Ich arbeite komplett mit den SDL-Funktionen. Was meinst du mit "Wieso sollte der Accept-Thread irgendwas anderes machen als Accept?"? Meine Idee war, das Accepten (ist non-blocking) mit in den Receive-Loop einzubauen. So oft kommen keine neuen Clients dazu - von daher würde ich ggf. auf einen extra Accept-Thread verzichten wollen.
Ich wiederhole: Ein Accept gehört meiner Meinung nach nicht in einen Receive-Loop, denn Receive selbst sollte wie select() arbeiten, die entsprechende SDL-Funktion wurde Dir ja schon genannt. Wenn man das aber so macht, müsste ein neuer Client so lange warten, bis ein anderer Daten schickt. Nicht mit einer Funktion wie select() zu arbeiten heißt Pollen, weil select() blockt und das sogar auf eine sehr sinnvolle Art und Weise. Polling ist nie gut aus diversen Gründen.

Was meinst du damit genau?
Delayed Ack und Nagle-Algorithm. Findet sich im Netz, kann ziemlichen Ärger bauen.

Also ein Send-Thread und ein Recv-Thread am Client?
Ja. Sinnvoller als Sleeps und Wait-Cycles wären hier aber Notifications/Events. Da es aber nur ein Client ist, sind Wait-Cycles oft eine gängige Lösung.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

simbad

unregistriert

46

21.03.2013, 12:33

Du solltest mal ausprobieren was passiert wenn du den Listener mit in das Socket-Set aufnimmst.
Mit select geht das völlig problemlos parallel auf eingehende Daten, auf die Schreiberlaubnis und auf eine listening socket zu warten.
Wenn die SDL funktion ebenfalls auf select basiert geht das vielleicht

Ein listener erzeugt, wenn ich nicht ganz falsch liege ein Read-Event wenn eine neue Verbindung reinkommt.

47

21.03.2013, 13:12

Ich wiederhole: Ein Accept gehört meiner Meinung nach nicht in einen Receive-Loop, denn Receive selbst sollte wie select() arbeiten, die entsprechende SDL-Funktion wurde Dir ja schon genannt. Wenn man das aber so macht, müsste ein neuer Client so lange warten, bis ein anderer Daten schickt. Nicht mit einer Funktion wie select() zu arbeiten heißt Pollen, weil select() blockt und das sogar auf eine sehr sinnvolle Art und Weise. Polling ist nie gut aus diversen Gründen.


Okay, also separater Accept-Thread :)

Delayed Ack und Nagle-Algorithm. Findet sich im Netz, kann ziemlichen Ärger bauen.


Ich meinte eher: wie könnte man das Senden beim Server optimieren?

Ein listener erzeugt, wenn ich nicht ganz falsch liege ein Read-Event wenn eine neue Verbindung reinkommt.


Ich kann nur soviel sagen: SDLNet_TCP_Accept liefert sofort den nächsten Client-Socket (der sich verbunden hat) oder NULL.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

48

21.03.2013, 13:16

Ich würde mir eher erstmal die Frage stellen, was der Server mit den empfangenen Daten eigentlich anstellen wird. Nehmen wir an, dass Senden und Empfangen gelöste Probleme sind, wie genau werden die Daten am Server verarbeitet?

49

21.03.2013, 13:36

Ich würde mir eher erstmal die Frage stellen, was der Server mit den empfangenen Daten eigentlich anstellen wird. Nehmen wir an, dass Senden und Empfangen gelöste Probleme sind, wie genau werden die Daten am Server verarbeitet?


Also meine Idee ist erstmal, dass der Server Anfragen der Clients empfängt (z.B. Bewegung nach <x,y>). Der Server reiht diese "Events" dann erstmal in einer Queue an. Die eigentliche serverseitige Spiellogik schnappt sich (wenn wir dabei mal von einem einzelnen Thread ausgehen) nacheinander die Events und arbeitet sie ab. D.h. sie schaut wo die Spielfigur (der bei einem RPG i.d.R. mit dem Client gleichzusetzen ist) aktuell steht und wo sie hin will (das steht im Event) und berechnet die Wegpunkte. Diese Wegpunkte gelangen dann in einem neuen Event (quasi die "Antwort") zurück zum Senden an den entsprechenden Client.

50

16.04.2013, 15:13

JSON-basierte Netzwerkkommunikation

Hallo,

in den letzten Wochen habe ich das Framework ein ganzes Stück umkonzipiert - auch basierend auf einigen der hier angesprochenen Probleme:

Kommunikation auf Basis von JSON
  • Daten werden in JSON-Objekten gesammelt und können serialisiert / deserialisiert werden. Die gängigen Container können in JSON-Objekte abgebildet werden.
  • Einige Speicherlecks beim Werfen von Exceptions wurden behoben. (aber sichtlich noch nicht alle!)
  • Beim Lesen der JSON-Objekte wird nicht mehr mit malloc und void-Pointern gearbeitet. Statt dessen wird auf das Mittel der Deserialisierung zurückgegriffen und ein neues JSON-Objekt erstellt, das mittels delete gelöscht werden kann. Dadurch wurden einige Speicherlecks behoben.
  • Probleme aufgrund verschiedener Größen von Datentypen wurden durch (die von C++11 gegebenen) Datentypen mit fester Länge (z.B. std::uint32_t - siehe http://en.cppreference.com/w/cpp/types/integer) eingedämmt. Soweit ich es überblicke, habe ich bereits das ganze Framework auf diese Typen umgebaut - oder fast das ganze ^^
  • Weitere plattformspezifische Probleme wurden durch die Serialisierung / Deserialisierung verringert. Mir ist derzeit erstmal kein weiteres Problem bewusst - ich bin aber offen für neue Probleme :D
  • Komprimierung ist bisher noch nicht eingebaut. Da aktuell aber serialisierte JSON-Objekte als Zeichenkette versandt werden, erscheint ein nachträgliches Implementieren einer Komprimierung bzw. Dekomprimierung recht einfach.
  • Bislang wird ausschließlich die Client-Server-Architektur unterstützt. Wenn jemand Interesse an einer Peer-to-Peer-Implementierung hat, kann ich da ggf. etwas bauen. Hat jemand eine Peer-to-Peer-Implementierung auf Basis des Frameworks, bin ich gerne bereit mir die anzuschauen und ggf. hinzuzufügen.
  • Es gibt aktuell genau eine Beispiel-Anwendung: Ein Konsolen-Chatroom. Siehe https://github.com/cgloeckner/networking

Es würde mich freuen, wenn der ein oder andere das Framework mal etwas auf den Zahl fühlen möchte. Für Fehler/Probleme/Anregungen/Kritik und Lob stehe ich gern zur Verfügung :)

Falls ich Eure Fragen noch nicht (vollständig) beantwortet habe, dann fragt bitte ruhig nochmal :)

LG Glocke

PS: Kann jemand das "Event-basiert" aus dem Titel nehmen? :D

Werbeanzeige