Client/Server Echtzeit per UDP - Architekturproblem



  • CCoax schrieb:

    rapso schrieb:

    was genau du schickst ist eigentlich deine sache, hauptsache du kannst die clients synchron halten.
    ...
    gegen packetloss hilft es, wenn du immer zwei packete zusammen schickst,

    (packet1|packet2)
    (packet2|packet3)
    (packet3|packet4)
    .
    .
    

    so hast du sehr selten das problem das du nen lag wegen packetlost bekommst.
    ...

    Gut, aber was passiert WENN ein Packet-Loss auftritt?
    Das war eigentlich meine zentrale Frage, da ein Packet-Loss ja zu einem Sync-Verlust führt...

    Ignoriere ich einfach die verlorenen Pakete?
    Das heisst wenn ich als Client 10 Pakete absende, die nicht ankommen, setze ich dann einfach den ClientState = Serverstate?

    Oder verwalte ich serverseitig mehrere Serverstates parallel zu unterschiedlichen Zeiten?

    Ich habe ein Problem damit, die verlorenen Client-Pakete zu resenden, weil ich nicht weiss, wie ich diese "veralteten" Pakete Serverseitig behandeln soll. Für diese Pakete ist der Zug ja schon abgefahren...
    Mehrere alte States zu verwalten erscheint mir aber irgendwie genauso unpassend. Oder ist Packet-Loss so selten? Wohl eher weniger, wenn ich deine Gamasutra-XWing Antwort Revue passieren lasse (Hatte den Artikel gelesen) 🙂

    Soweit ich weiss ist Packet-Loss wohl das Hauptproblem...

    bis hier,
    Coax

    das hängt ganz vom spiel und von den daten ab die du versendest.

    wenn du z.b. einen shooter machst und immer die aktuelle position und den richtungsvector schickst, dann kanst du bei packetloss drauf verzichten ein verlorenes packet nochmal zu schicken, das bringt zwar ein paar kleine fehler mitsich, aber bei netzwerk dingen bei denen es sehr auf ping ankommt, muss man fehlertollerante protokolle nutzen.

    wenn es sehr wichtig ist, dass du alle packete übermittelt hast, dann mußt du einen cache einbauen in dem du dir die gesendeten packete hällst.
    Die verbindungspartner müssen sich dann in ihren packeten auch immer schicken welches die größte ID der nach der reihe empfangenen packete ist, die packete mit der ID udn kleinere kannst du dann sorglos löschen.
    natürlich könnte es bei schlechter verbindung passieren dass beide ihre packete nicht empfangen, dafür mußt du ein timeout machen.
    wenn du z.b einen shooter hast, wäre ein timeout von vielleicht 500ms schon gross genug. dann mußt du die letzten packete entweder neu schicken oder meldest dem user ein connection-loss.

    dass es mehrere verbindungen gibt, davon geh ich eh aus. die meißten spiele haben eine UDP verbindung für schnell zu übermittelnde daten, die aber auf einem fehlertolleranten protokoll basieren (z.b. aktuelle position, richtungsvector und timestamp).
    und es gibt eine tcp verbindung, z.b. für chat, textureupload, trading-system usw.

    aber ich SnorreDev hat scho räscht, ohne zu wissen welche art von anforderungen dein spiel hat, kann man keine spezialisierte optimierung empfehlen.

    rapso->greets();



  • Yupp, Sorry.

    Hätte wohl eher zeitkritisch anstatt Echtzeit im Threadtitel schreiben sollen, das Spiel soll zwar mal kein Shooter im eigentlichen Sinne werden, hat aber auf jeden Fall die gleichen Anforderungen. Hier groß etwas dazu zu sagen wäre aber sinnlos, denn die unterste Ebene bildet hier nun mal networking, ohne ein funktionierendes Client/Server System brauch ich das Spiel noch garnicht anpacken...
    Vielleicht als Stichwort(e):
    Oldschool Iso-Shooter in Pseudo2D (OGL)

    Zum Thema:

    Naja - je nachdem wie der Netzwerkaufbau ist - ich wuerde in Reliable, Unreliable und Immediate Packages unterscheiden.

    Schließe ich nicht aus, allerdings finde ich die Möglichkeit unpraktisch. Dann wäre wahrscheinlich Rapsos Idee besser, per TCP/IP wirklich relevante Daten wie Verbindungsaufbau oder Leveldownload u.ä. zu verwalten.

    ***** Betrifft mehrere Pakete in einem *****
    Wuerde ich nur tun, wenn es nicht Online, sondern nur im LAN gespielt wird, denn du bekommst schnell Traffic Probleme.

    Gerade im Lan ist es eigentlich sinnlos, weil da korrekte Lieferung schon fast garantiert wird, IMO 😉

    wenn du z.b. einen shooter machst und immer die aktuelle position und den richtungsvector schickst, dann kanst du bei packetloss drauf verzichten ein verlorenes packet nochmal zu schicken,[...]

    Genau das tue ich, nachdem ich die Pakete delta-komprimiert habe. Die werden also wahrscheinlich ziemlich klein, weshalb ich auch deshalb schon mehrere in ein Paket packen könnte. Das verlorene Paket wird auch größtenteils durch Dead-Reckoning "verschleiert". Also müsste ich für diesen Ansatz wirklich die emulierte Version des Servers nehmen, um Interaktion zu berechnen. Dieses würde natürlich nur für kurze Zeiträume gelten, und evtl. ein Problem darstellen, wenn geschossen wird, da hat SnorreDev absolut Recht.

    wenn es sehr wichtig ist, dass du alle packete übermittelt hast, dann mußt du einen cache einbauen in dem du dir die gesendeten packete hällst.
    Die verbindungspartner müssen sich dann in ihren packeten auch immer schicken welches die größte ID der nach der reihe empfangenen packete ist, die packete mit der ID udn kleinere kannst du dann sorglos löschen.

    ACK, bis auf eine gleiche ID, die könnte man evtl. verwenden um den Puffer zurückzusetzen (Clientseitig). Es tauschen eh beide Parteien (Server/Client) die jeweils empafangenen Paket-IDs aus, quasi Huckepack im regulären Paket. Ich will es auf jeden Fall vermeiden, eine "angekommen" Nachricht zum Client zu schicken, nur um der Nachricht willen.

    Aber genau in deinem angesprochenen Cache liegt mein Verständnisproblem. Wenn ein Client Probleme hat, darf ich IMO nicht den Server bremsen, um die verlorenen Pakete nachzuholen. Das wäre ziemlich exakt der TCP-Effekt den ich vermeiden will. Wie aber muss ich den Server aufbauen, bzw. das Cache-Handling, um dem "verlorenen" Client wieder korrekt einzuweisen, ohne das die anderen was davon merken. Player-Bouncing des betreffenden Clients wie man das aus Internetpartien in Shootern kennt lässt sich nicht vermeiden, aber ich kann mir den internen Ablauf nicht wirklich vorstellen.

    Den wenn ein Client auf den anderen (gelossten) Client feuert, aber nur die Server-Interpretierte Version trifft, ist der gelosste Player für den Server tot (und damit auch für alle anderen Spieler). Nun kommt das Packet an, welches vermisst wurde, der Server kann die korrekte Position des gelossten Clients ermitteln. Und jetzt gibts einen Konflikt:

    Ich kann ja wohl schlecht die Zeit wieder zurückdrehen und der gelosste Client lebt auf einmal wieder, weil die korrekte Position nicht in der Schussbahn des anderen Clients liegt.

    Ich hoffe ich konnte die Problematik jetzt klarer darstellen 🙂



  • das läuft schon immer so, dass nur die serverdaten als die verlässlichen gelten. wenn also ein client einen lag hat und abgeschossen wird obwohl er in wirklichkeit 'bei sich' rumläuft, dann ist der client halt tod. das lässt sich nicht ändern, das war schon bei doom1 so 😉
    bei diesen spielen wird ja auch nicht udp benutzt um tcp nachzubilden, das sind dann die fehlertolleranten protokolle (wie schon mehrfach erwähnt, z.b. position, richtungsvector, timestamp). dort ist es dir egal, ob du nen packetloss hast, das wirkt sich nur zum nachteil für den einen spieler aus, der eine schlechte verbindung hat, alle anderen können spielen.

    rapso->greets();



  • rapso schrieb:

    das läuft schon immer so, dass nur die serverdaten als die verlässlichen gelten. wenn also ein client einen lag hat und abgeschossen wird obwohl er in wirklichkeit 'bei sich' rumläuft, dann ist der client halt tod. das lässt sich nicht ändern, das war schon bei doom1 so 😉
    bei diesen spielen wird ja auch nicht udp benutzt um tcp nachzubilden, das sind dann die fehlertolleranten protokolle (wie schon mehrfach erwähnt, z.b. position, richtungsvector, timestamp). dort ist es dir egal, ob du nen packetloss hast, das wirkt sich nur zum nachteil für den einen spieler aus, der eine schlechte verbindung hat, alle anderen können spielen.

    rapso->greets();

    Wenn dem tatsächlich so ist, funktioniert das Internet wohl zuverlässiger als ich dachte.
    Dann werde ich erst mal ein redundantes System aufbauen und ggf. später erweitern.

    THX,
    Coax



  • zogg einfach mal doom auf einem sehr langsamen rechner gegen einen fixen. Ich hab miterlebt wie jemand bei mir schon tod war und auf dem nachbarrechner das neue frame noch nicht dargestellt wurde in dem er tod ist 🙂

    du kannst dich auch auf nen server mit nem ping von 500ms verbinden, da wirst du auch miterleben dass du relativ oft gekillt wirst, nicht weil die anderen so gut zielen, sondern weil du für den server für 500ms eine konstante bewegung durchläufst und dann natürlich getroffen wirst.

    rapso->greets();



  • Mhhh...
    Spontan habe ich nur Q3A im Kopf, und dort zischen nach einem Lag auf einmal alle wie wild im Zeitraffer durch die Gegend, oder es gibt einen deconnect. Bei schlechter Verbindung im allgemeinen gibts massives Player-Bouncing.

    Ich kenne nur leider die ganz grobe Arbeitsweise des Q3-Servers...

    rapso schrieb:

    du kannst dich auch auf nen server mit nem ping von 500ms verbinden, da wirst du auch miterleben dass du relativ oft gekillt wirst, nicht weil die anderen so gut zielen, sondern weil du für den server für 500ms eine konstante bewegung durchläufst und dann natürlich getroffen wirst.

    Ich sterb' wohl eher, weil ich so schlecht bin 🙄

    Aber ich denke du hast da Recht...bin schon wahnsinnig oft durch solche "seltsamen" Verhältnisse gestorben. Jetzt muss ich nur noch dazu kommen, den Kram in diesem Leben umzusetzen. Böse knappe Zeit.

    Coax



  • CCOAX schrieb:

    Ich sterb' wohl eher, weil ich so schlecht bin 🙄

    *chrrrr* Is' klar, Meister der Railgun und Trickjump-Guru!! 😃



  • Sgt. Nukem schrieb:

    CCOAX schrieb:

    Ich sterb' wohl eher, weil ich so schlecht bin 🙄

    *chrrrr* Is' klar, Meister der Railgun und Trickjump-Guru!! 😃

    du hast "verführer all unserer (ex)freundinen vergessen" *hehe*

    rapso->greets();



  • rapso schrieb:

    Sgt. Nukem schrieb:

    CCOAX schrieb:

    Ich sterb' wohl eher, weil ich so schlecht bin 🙄

    *chrrrr* Is' klar, Meister der Railgun und Trickjump-Guru!! 😃

    du hast "verführer all unserer (ex)freundinen vergessen" *hehe*

    Kennst Du den Kerl auch?!?! 😕

    😃 👍



  • rapso schrieb:

    Sgt. Nukem schrieb:

    CCOAX schrieb:

    Ich sterb' wohl eher, weil ich so schlecht bin 🙄

    *chrrrr* Is' klar, Meister der Railgun und Trickjump-Guru!! 😃

    du hast "verführer all unserer (ex)freundinen vergessen" *hehe*

    rapso->greets();

    😉 Und du hast vergessen, auch die zukünftigen Freundinnen zu erwähnen...



  • um wieviel langsamer ist TCP gegenüber UDP?

    Ich habe ein ähnliches problem (Client-Syncronisierung)
    habe aber mein Spiel auf TCP aufgebaut...

    Wie funktioniert das mit dem Timestamp in den Paketen?



  • Rodney schrieb:

    um wieviel langsamer ist TCP gegenüber UDP?

    Ich habe ein ähnliches problem (Client-Syncronisierung)
    habe aber mein Spiel auf TCP aufgebaut...

    Wie funktioniert das mit dem Timestamp in den Paketen?

    😕



  • Kann man nicht so genau sagen.
    Und kommt auf den Anwendungsfall an.
    Ein Schachspiel z.B. würde ich der Einfachheit halber nur auf TCP aufbauen.



  • Vor allem hätte UDP da keine Vorteile.



  • nman schrieb:

    Vor allem hätte UDP da keine Vorteile.

    Doch natürlich.
    Durch die geringe Paketgrösse und das "verbindungslose" kommen die Päckchen schneller an (falls sie ankommen).

    Was Du wahrscheinlich (richtigerweise) meinst, ist, daß man bei einem rundenbasierten Spiel wie Schach da jetzt nicht sooo drauf achten muß, und der Nutzen eher gering ist... 😉 🕶



  • Sgt. Nukem schrieb:

    Doch natürlich.
    Durch die geringe Paketgrösse und das "verbindungslose" kommen die Päckchen schneller an (falls sie ankommen).

    Was Du wahrscheinlich (richtigerweise) meinst, ist, daß man bei einem rundenbasierten Spiel wie Schach da jetzt nicht sooo drauf achten muß, und der Nutzen eher gering ist... 😉 🕶

    Naja, dass bei Schach die Latenz sch...egal ist, ist natürlich klar; aber UDP hätte hier den Nachteil dass man erst aufwändig eine Möglichkeit implementieren müsste, festzustellen, ob Pakete vollständig angekommen sind, da es doch verdammt unpraktisch wäre, wenn was verlorenginge. (Wow, so viele Beistriche in einem Satz...)

    Und Schachzüge brauchen ja nicht größer sein als "MV A:3 B:3" oä... 😉



  • Exakt.

    Nichtdestotrotz hat UDP den Geschwindigkeitsvorteil... :p


Anmelden zum Antworten