Frage zu Netzwerkprotokoll


  • Mod

    hustbaer schrieb:

    Das 64k Limit ist soweit ich das beurteilen kann eine "Urban Legend".

    es ist also dein glauben vs die legend, spannender fight ;).

    da ich das vor ewigkeiten auch mal wissen wollte, hab ich natuerlich nachgesehen. windows95 hatte 255sockets als limit, winNT hatte 65535.

    Wie das zZ ist sollte man einfach irgendwo raussuchen statt das hier jeder was anderes postet 😉



  • Pyr0kar schrieb:

    Blödsinn. Wenn du die Clientseite entscheiden lässt, welche Spieler angegriffen werden können, ist dein Spiel ziemlich unsicher.

    grml 😕
    Wenn der Client die Information, dass xyz ein NPC ist, anders interpretieren würde, würde das Spiel auf ihm nicht mehr synchron mit dem Server laufen. Du kannst daraus keinen Hack schlagen. Du kannst ja sinnloserweise gerne eine Nachricht "Möchte attackieren" absenden, aber auf dem Client auch noch die Kampf Animation/Musik etc. beim Angriff eines NPCs abzuspielen, wäre vermutlich nicht wirklich im Interesse des Spiels.



  • krabbels schrieb:

    Pyr0kar schrieb:

    Blödsinn. Wenn du die Clientseite entscheiden lässt, welche Spieler angegriffen werden können, ist dein Spiel ziemlich unsicher.

    grml 😕
    Wenn der Client die Information, dass xyz ein NPC ist, anders interpretieren würde, würde das Spiel auf ihm nicht mehr synchron mit dem Server laufen. Du kannst daraus keinen Hack schlagen. Du kannst ja sinnloser weise gerne eine Nachricht "Möchte attackieren" absenden, aber auf dem Client auch noch die Kampf Animation/Musik etc. beim Angriff eines NPCs abzuspielen, wäre vermutlich nicht wirklich im Interesse des Spiels.

    Hast du dir überhaupt mal mein Beispiel angeschaut?

    In "kalonline" _kann_ man in der Tat sehr gut einen Hack daraus schlagen, dass nicht serverseitig überprüft wird ob der Angriff stattfinden darf.

    Du kannst vom einen Ende der gesamten Map ein anderes Monster auf dem anderen Ende angreifen, wenn du es selektiert hast.
    Du kannst das Vieh damit sogar töten, geht alles wunderbar.

    Und das nur, weil der Client einfach "greife NPC ... an" sendet und der server so blöd ist, und es einfach tut und die HP abzieht.

    Der Server sollte die anfrage prüfen (auf Reichweite, Befreundete Spieler usw.) und seine Antwort dem Client schicken, damit dieser weiß, ob er die Animation abzuspielen hat oder nicht, ist nämlich ziemlich blöd wenn der Client die Angriffsanimation abspielt und der Mob keine HP verliert.

    Wenn du Hacks vermeiden willst kommst du um eine serverseitige Überprüfung nicht drum herum.

    Den Client zu cheaten/bearbeiten ist immer möglich, ob das nun schwer oder leicht gemacht wird ist eine andere sache, bei kalonline wird es leicht gemacht.

    Den Server zu cheaten/bearbeiten wird ziemlich schwer ohne physikalischen Zugang.

    Wenn der Client die Information, dass xyz ein NPC ist, anders interpretieren würde, würde das Spiel auf ihm nicht mehr synchron mit dem Server laufen. Du kannst daraus keinen Hack schlagen.

    Ein Memory-Editor sorgt eigentlich ganz schnell dafür, dass der _Client_ denkt, es sei ein nicht-befreundeter. Da lässt sich super ein Hack draus schlagen.

    Mit der Reichweite dauert das z.b. bei einigen Onlinespielen nur wenige Sekunden mit dem richtigen Programm die Speicherstellen zu bearbeiten und es funktioniert super.

    Ein gutes Spiel würde sich selbst nicht cheaten lassen, wenn du den Source von deinem Client freigibst. Du musst immer damit rechnen dass jemand den Client umbiegt, der Server muss damit klar kommen und darf nicht falsch handeln.

    Alles andere is Security through obscurity (siehe http://de.wikipedia.org/wiki/Security_through_obscurity)



  • Pyr0kar schrieb:

    In "kalonline" _kann_ man in der Tat sehr gut einen Hack daraus schlagen, dass nicht serverseitig überprüft wird ob der Angriff stattfinden darf.

    Du schickst an den Server die Nachricht "Möchte attackieren" also wird es doch serverseitig überprüft. Niemand spricht davon, dass es nicht so sein sollte. Der Client braucht nun aber keine Rückbestätigung mehr. Der Client kann Ereignisse gerne anders interpretieren; Er kann aus NPCs Blumen machen, aus Häusern Bäume und Schwertern Atombomben. Das tatsächliche Spiel findet aber auf dem Server statt, wo Schwerter eben keine Atombomben sind.

    Pyr0kar schrieb:

    Der Server sollte die anfrage prüfen (auf Reichweite, Befreundete Spieler usw.)

    Richtig. Und anschließend das tatsächliche Spiel aktualisieren.

    Pyr0kar schrieb:

    und seine Antwort dem Client schicken, damit dieser weiß, ob er die Animation abzuspielen hat oder nicht, ist nämlich ziemlich blöd wenn der Client die Angriffsanimation abspielt und der Mob keine HP verliert.

    Nein. Der Client weiß selber, dass er da einen NPC angreifen will also braucht er gar keine Animation zu starten, da er die Antwort vom Server bereits kennt.

    Pyr0kar schrieb:

    Ein Memory-Editor sorgt eigentlich ganz schnell dafür, dass der _Client_ denkt, es sei ein nicht-befreundeter. Da lässt sich super ein Hack draus schlagen.

    Wenn der Client durch einen Hack NPCs für angreifbar oder Schwerter für Atombomben hält, kann er das gerne machen. Der Server wird die Zusammenarbeit aber verweigern. Die beiden Spiele laufen nicht mehr synchron.
    Verstehst du es nun?



  • Achso, krabbels, du meinst dass eine Prüfung sowohl clientseitig als auch serverseitig stattfinden soll? Würde sogar traffic einsparen.

    Client will NPC angreifen -> Verweigert, da Client überprüft

    -Client wird gehackt-

    Client sendet Paket zum NPC angreifen -> Server verweigert, da überprüft

    MfG



  • ceplusplus schrieb:

    Achso, krabbels, du meinst dass eine Prüfung sowohl clientseitig als auch serverseitig stattfinden soll? Würde sogar traffic einsparen.

    Client will NPC angreifen -> Verweigert, da Client überprüft

    -Client wird gehackt-

    Client sendet Paket zum NPC angreifen -> Server verweigert, da überprüft

    MfG

    Korrekt. Auf beiden Seiten läuft ja das gleiche Spiel, von daher liegt das nur Nahe. Es würde ja imho auch keinen Sinn machen die Spiele-Logik beim Client auszuschalten. Vielmehr entstehen dadurch enorme Probleme, da der Client in der Zeit, in der er keine Daten vom Server erhält nichts machen kann. Nehmen wir an, der Abgleich mit dem Server findet nur 3 mal pro Minute statt, dann würde eine Aktualisierung des Client-States auch nur 3 mal pro Minute geschehen. Ich glaube, das hemmt dann doch den Spielspass ein wenig.



  • Thomy schrieb:

    Dass es aber mehr als 2^16 Ports gibt, bezweifele ich trotzdem!
    Man sieht doch praktisch überall nur Einstellungen und co., die von "0"-65535 gehen!

    Es gibt auch nur 2^16 Ports, du darfst aber Ports nicht mit Sockets verwechseln.

    rapso schrieb:

    hustbaer schrieb:

    Das 64k Limit ist soweit ich das beurteilen kann eine "Urban Legend".

    es ist also dein glauben vs die legend, spannender fight ;).

    da ich das vor ewigkeiten auch mal wissen wollte, hab ich natuerlich nachgesehen. windows95 hatte 255sockets als limit, winNT hatte 65535.

    Wie das zZ ist sollte man einfach irgendwo raussuchen statt das hier jeder was anderes postet 😉

    Also hier steht was von 100k in der 32 Bit Version und 1m in der 64 Bit Version. Beides > 64k.

    http://download.microsoft.com/download/5/8/7/587312a9-d421-4f07-9d9e-b6515720082b/perfscal.doc


  • Mod

    hustbaer schrieb:

    Thomy schrieb:

    Dass es aber mehr als 2^16 Ports gibt, bezweifele ich trotzdem!
    Man sieht doch praktisch überall nur Einstellungen und co., die von "0"-65535 gehen!

    Es gibt auch nur 2^16 Ports, du darfst aber Ports nicht mit Sockets verwechseln.

    rapso schrieb:

    hustbaer schrieb:

    Das 64k Limit ist soweit ich das beurteilen kann eine "Urban Legend".

    es ist also dein glauben vs die legend, spannender fight ;).

    da ich das vor ewigkeiten auch mal wissen wollte, hab ich natuerlich nachgesehen. windows95 hatte 255sockets als limit, winNT hatte 65535.

    Wie das zZ ist sollte man einfach irgendwo raussuchen statt das hier jeder was anderes postet 😉

    Also hier steht was von 100k in der 32 Bit Version und 1m in der 64 Bit Version. Beides > 64k.

    http://download.microsoft.com/download/5/8/7/587312a9-d421-4f07-9d9e-b6515720082b/perfscal.doc

    schaut wie Marketing BS aus.
    man sollte man-pages oder msdn bevorzugen. siehe: http://msdn2.microsoft.com/en-us/library/ms739169.aspx



  • krabbels schrieb:

    ceplusplus schrieb:

    Achso, krabbels, du meinst dass eine Prüfung sowohl clientseitig als auch serverseitig stattfinden soll? Würde sogar traffic einsparen.

    Client will NPC angreifen -> Verweigert, da Client überprüft

    -Client wird gehackt-

    Client sendet Paket zum NPC angreifen -> Server verweigert, da überprüft

    MfG

    Korrekt. Auf beiden Seiten läuft ja das gleiche Spiel, von daher liegt das nur Nahe. Es würde ja imho auch keinen Sinn machen die Spiele-Logik beim Client auszuschalten. Vielmehr entstehen dadurch enorme Probleme, da der Client in der Zeit, in der er keine Daten vom Server erhält nichts machen kann. Nehmen wir an, der Abgleich mit dem Server findet nur 3 mal pro Minute statt, dann würde eine Aktualisierung des Client-States auch nur 3 mal pro Minute geschehen. Ich glaube, das hemmt dann doch den Spielspass ein wenig.

    *zustimm*

    Nur schade, dass dadurch die gleiche Prüfung 2x im Programmcode vorkommt, einmal im Client und einmal im Server.
    Oder würdet ihr dafür eine Lib oder was ähnliches coden und von beiden benutzen lassen?



  • rapso schrieb:

    hustbaer schrieb:

    Thomy schrieb:

    Dass es aber mehr als 2^16 Ports gibt, bezweifele ich trotzdem!
    Man sieht doch praktisch überall nur Einstellungen und co., die von "0"-65535 gehen!

    Es gibt auch nur 2^16 Ports, du darfst aber Ports nicht mit Sockets verwechseln.

    rapso schrieb:

    hustbaer schrieb:

    Das 64k Limit ist soweit ich das beurteilen kann eine "Urban Legend".

    es ist also dein glauben vs die legend, spannender fight ;).

    da ich das vor ewigkeiten auch mal wissen wollte, hab ich natuerlich nachgesehen. windows95 hatte 255sockets als limit, winNT hatte 65535.

    Wie das zZ ist sollte man einfach irgendwo raussuchen statt das hier jeder was anderes postet 😉

    Also hier steht was von 100k in der 32 Bit Version und 1m in der 64 Bit Version. Beides > 64k.

    http://download.microsoft.com/download/5/8/7/587312a9-d421-4f07-9d9e-b6515720082b/perfscal.doc

    schaut wie Marketing BS aus.
    man sollte man-pages oder msdn bevorzugen. siehe: http://msdn2.microsoft.com/en-us/library/ms739169.aspx

    Wieso Marketing BS? Ich finde die Grenze 100k bzw. 1m ist lächerlich niedrig, auf jeden Fall niedrig genug um glaubhaft zu sein.

    In dem von dir verlinkten Artikel steht nur "The maximum number of sockets supported by a particular Windows Sockets service provider is implementation specific. "

    Und das Makro FD_SETSIZE beeinflusst nur wie gross man ein "fd_set" mit den Berkeley kompatiblen Makros (FD_ZERO, FD_SET, ...) machen kann. Wenn man die Werte selbst in ein int/LONG/ULONG Array schreibt muss man FD_SETSIZE nicht definieren (kann aber trotzdem > 64 Sockets in einem select verwenden). Genauso wenn man select() nicht verwendet sondern WSAAsyncSelect/WSAEventSelect oder IO completion ports.

    Hat auf jeden Fall nichts damit zu tun wieviel Sockets das OS wirklich unterstützt.



  • ok, wusste nicht, dass Sockets was anderes ist als Ports!
    Ist mir so auf jedenFall lieber!

    Wenn man mehr als 100k Spieler aufm Server hat, macht man sich vllt. darüber Gedanken, dass man die Welt auf mehrere Server aufteilt oder doch ein anderes System benutzt als Windows XP mit dynamischen DNS! 😉



  • Pyr0kar schrieb:

    Nur schade, dass dadurch die gleiche Prüfung 2x im Programmcode vorkommt, einmal im Client und einmal im Server.
    benutzen lassen?

    Bei halbwegs sauberer Programmierung ist das nicht nötig. Da kannst du dann die zusätzlichen Möglichkeiten, die ein Client oder Server bieten muss einfach "aufsetzen" und brauchst den Code nicht doppelt zu schreiben.


  • Mod

    hustbaer schrieb:

    Wieso Marketing BS?

    Und das Makro FD_SETSIZE beeinflusst nur wie gross man ein "fd_set" mit den Berkeley kompatiblen Makros (FD_ZERO, FD_SET, ...) machen kann. Wenn man die Werte selbst in ein int/LONG/ULONG Array schreibt muss man FD_SETSIZE nicht definieren (kann aber trotzdem > 64 Sockets in einem select verwenden). Genauso wenn man select() nicht verwendet sondern WSAAsyncSelect/WSAEventSelect oder IO completion ports.

    seltsam, du glaubst dem marketing document, aber wenn in der programmier database woertlich steht steht:

    The maximum number of sockets that an application can actually use is independent of the number of sockets supported by a particular implementation. The maximum number of sockets that a Windows Sockets application can use is determined at compile time by the manifest constant FD_SETSIZE.

    sagst du dass es irrelevant ist was FD_SETSIZE fuer eine bedeutung hat laut documentation.



  • rapso schrieb:

    hustbaer schrieb:

    Wieso Marketing BS?

    Und das Makro FD_SETSIZE beeinflusst nur wie gross man ein "fd_set" mit den Berkeley kompatiblen Makros (FD_ZERO, FD_SET, ...) machen kann. Wenn man die Werte selbst in ein int/LONG/ULONG Array schreibt muss man FD_SETSIZE nicht definieren (kann aber trotzdem > 64 Sockets in einem select verwenden). Genauso wenn man select() nicht verwendet sondern WSAAsyncSelect/WSAEventSelect oder IO completion ports.

    seltsam, du glaubst dem marketing document, aber wenn in der programmier database woertlich steht steht:

    The maximum number of sockets that an application can actually use is independent of the number of sockets supported by a particular implementation. The maximum number of sockets that a Windows Sockets application can use is determined at compile time by the manifest constant FD_SETSIZE.

    sagst du dass es irrelevant ist was FD_SETSIZE fuer eine bedeutung hat laut documentation.

    Ja, sage ich, und zwar ganz ausdrücklich.
    Die Doku ist schlecht geschrieben.



  • Dass der Klient auch die Daten prüft ist auf jedenfall wichtig, denke ich. Das spart Serverseitig in den meisten Fällen viel Leistung und stellt ein flüssiges Spielerlebnis sicher. Greift der Spieler durch Hack einen NPC an, wird ja - wie schon gesagt - das ganze geprüft und der Server kann den GameState vom Client anfordern um diesen an einen der Mitarbeiter zu schicken die auf Bugs und/oder Exploits prüfen. So kann gegebenenfalls ein Spieler verwarnt/ausgeschlossen werden oder ein Bug gefunden werden.

    Die NPCs etc. werden ja beim Laden der Zone vom Server an den Klienten geschickt (bzw ihre Status-Variablen). Von da an weiss der Klient, dass er diese nicht angreifen kann. Macht er es doch, gibt es einen Disconnect und halt eventuell Ärger durch das Team 🙂

    Gruss, Andi



  • Hallo, ich finde die Überlegungen sehr interessant und habe auch noch eine Frage:

    Was nimmt man denn jetzt am Besten TCP oder UDP?

    Ich sehe bei beidem Probleme:

    TCP: Ich greie an. Das Paket kommt aber nicht an (z.B kurze Leitungsstörung)
    TCP sendet erneut. Der Client sieht den Angriff aber schon (da die Animation sofort gestartet wurde, aber kein Schaden entsteht)

    Das ist doch irretierend für den Spieler.

    UDP: Keine Verzögerungen, weil das Paket nicht neu gesendet wird. Client sieht den Angriff. Da das Paket verlohren geht wird der Angiff nie ausgelöst beim server. Schaden wird nie eintreten, doch client sieht einen Angriff.

    Wieder irretierend für den Spieler.

    Wie geht man mit diesem Problem um?



  • Andreas XXL schrieb:

    Wie geht man mit diesem Problem um?

    Wenn man UDP verwendet, muss man sich per Protokoll selbst drum kümmern, Pakete sicher zuzustellen.



  • Was ich dabei aber nicht verstehe ist, dass die Pakete ja ankommen müssen!
    Und dafür kann man doch dann TCP verwenden, oder, dafür ist es ja da!?
    UDP würde ich nur bei "Aktuelle Spielposition" verwenden!



  • UDP: Keine Verzögerungen, weil das Paket nicht neu gesendet wird. Client sieht den Angriff. Da das Paket verlohren geht wird der Angiff nie ausgelöst beim server. Schaden wird nie eintreten, doch client sieht einen Angriff.

    Nö. Wenn du UDP verwenden willst musst du dir selbst einen "reliability layer" dazubasteln. Nur kannst du dann selbst bestimmen was genau wann genau erneut übertragen wird.
    z.B.:

    UDP: Keine Verzögerungen. Die Information "ich greife Spieler X mit Waffe Y an" geht sofort mit dem nächsten Paket wieder raus, solange bis eine Bestätigung eingetroffen ist. Da so eine Information üblicherweise "selten" gesendet wird ("selten" z.B. im Vergleich zu Richtungsänderungen beim Rumlaufen) und nur ein paar wenige Bytes in Anspruch nimmt kann man sich das leisten. Irgendwann geht das Paket durch, und die Information landet beim Server. Das Paket wird bestätigt, und nach Empfang der Bestätigung kann die Information am Client gelöscht werden, und muss nicht weiter mit jedem Paket mitgeschickt werden.
    Im Normalfall kann man davon ausgehen dass die Verzögerung die dadurch entsteht deutlich geringer ist als bei TCP, da TCP im Vergleich dazu lange braucht um den Fehler festzustellen.

    Natürlich wird man nicht jede Information mit jedem Paket schicken bis sie bestätigt wurde, aber da man es selbst programmiert kann man Informationen in verschiedene Klassen unterteilen. Ein Angriff ist wichtig und wird höchste Priorität haben. Ein "ich habe Item X aufgeklaubt" wird weniger Priorität haben, zumindest wenn keine andere Spieler in meiner Umgebung sind die mir Item X wegschnappen könnten.
    Eine Chat Message wird u.U. noch weniger Priorität haben.

    Weiters kann man unterscheiden welche Informationen/Ereignisse 1:1 so übertragen werden müssen wie sie auftreten, und auch in der gleichen Reihenfolge ausgewertet ("Waffe X nehmen" muss VOR "mit Wafft X angreifen" ausgewertet werden, da der Server sonst "kann nicht sein!" schreien würde), bzw. welche anderen Informationen/Ereignisse nicht in der korrekten Reihenfolge ausgewertet werden müssen (Chat Nachricht muss z.B. nicht mit Vorgängen im Spiel synchronisiert werden), oder bei welchen Daten es nur wichtig ist den Letztstand zu kennen, Zwischenstände aber nichtmehr interessant sind sobald man schon einen neueren Zustand empfangen hat (z.B. Health Werte von anderen Spielern oder deren Position).

    ----

    Üblicherweise verwendet man für sowas (den "reliability layer") fertige Libraries. Wer sich für sowas interessiert kann sich z.B. die RakNet ansehen. (Der Source ist frei verfügbar, kommerzielle Lizenzen äusserst billig, und im Moment steht auf der Homepage was vonwegen "Creative Commons Attribution - NonCommercial 2.5" für "Non-profit applications or engines" -- einfachen selber gucken wens interessiert).

    ----

    Thomy schrieb:

    Was ich dabei aber nicht verstehe ist, dass die Pakete ja ankommen müssen!
    Und dafür kann man doch dann TCP verwenden, oder, dafür ist es ja da!?
    UDP würde ich nur bei "Aktuelle Spielposition" verwenden!

    Siehe oben.
    TCP kann auch nicht zaubern, alles was TCP kann kann man auch selbst mit UDP "nachbilden". Da man so (mit UDP + reliability Marke Eigenbau) dann selbst bestimmen kann welche Kompromisse man eingeht (z.B. mehr (redundante) Daten verschicken, dafür weniger Latenz in dem Fall dass ein Paket verloren gegangen ist), ist man einfach flexibler.

    Auch kann man mit UDP mehrere logische Datenströme parallel verwalten die z.B. in sich, aber nicht untereinander synchronisiert werden müssen uswusf.


  • Mod

    Andreas XXL schrieb:

    Was nimmt man denn jetzt am Besten TCP oder UDP?

    wenn es um rollenspiele geht nimmt man oft beides soweit ich weiss. wichtige dinge(spieleingreifende) und nicht zeitkritische (z.b. texturen streamen) werden ueber tcp abgehandelt, dinge die zeitkritisch sind dann ueber udp, weil es egal ist ob sie nicht ankommen oder sehr viel verspaetet ankommen, die daten sind dann schon nutzlos.

    TCP: Ich greie an. Das Paket kommt aber nicht an (z.B kurze Leitungsstörung)
    TCP sendet erneut. Der Client sieht den Angriff aber schon (da die Animation sofort gestartet wurde, aber kein Schaden entsteht)

    Das ist doch irretierend für den Spieler.

    das ist ganz normal und merkt kaum ein spieler. viele rollenspiele leben noch gut mit pings von 500ms. wenn du einen angriff startest, wird sofort das packet geschickt, deine figur fuchtelt noch ne sekunde rum bis der gegner getroffen ist und bis dahin ist das antwortpacket laengst beim spieler angekommen welche zahl aufblinken soll. wie hustbaer sagte, kann das auch ueber einen eigenen layer auf udp passieren.

    zeitkritische dinge waeren eher wenn im 20ms bereich etwas passieren soll. 500ms ist ne ewigkeit.


Anmelden zum Antworten