Sockets und Paketorientierte datenübertragung



  • Da das ich grad n anderes Topic mit ähnlichem inhalt gesehen habe wollt ich an der stelle mal nach ner idee fragen zur paketorientierten übertragung für streamsockets.

    es geht darum mehrere "steuerimpulse" zu übertragen also wenn an PC A jemand auf pfeil-hoch drückt soll n datenpaket mit befehl 1 übertragen werden .... gut dazu würde nen simpler char wert reichen, allerdings sollen da noch einige komplexere daten hinzukommen, die frage ist wie kann ich effektiv in einem TCP socket mehrere aufeinanderfolgende "pakete" klar abgrenzen, hat da jemand eventuell einen effektiven ansatz?!

    meine bisherige umsetzung besteht bei minimaler sicherheit in der übertragung eines 4byte großen blockanfang, mit darauffiolgender 1byte großen datalen, darauf folgt die befehlsID und die daten die icih je nach der ID auswerte.

    bei maximaler sicherheit übertrage ich auch ein endzeichen, kann ich dieses nicht finden verwerfe ich das paket und suche in den vorhergehenden daten nach einem neuen anfangssignal bis ich eins gefunden habe oder der datenstrom endet



  • Ceos schrieb:

    bei maximaler sicherheit übertrage ich auch ein endzeichen, kann ich dieses nicht finden verwerfe ich das paket und suche in den vorhergehenden daten nach einem neuen anfangssignal bis ich eins gefunden habe oder der datenstrom endet

    das brauchst du nicht zu machen. TCP sorgt automatisch dafür, dass nichts fehlt. entweder alles ist da oder die verbindung bricht ganz ab. dass einzelne bytes ausgelassen werden, kann nicht passieren.
    🙂



  • Eine andere, relativ einfach Loesung fuer dein Problem wird es wohl auch nicht geben. Entweder ein Header mit Laenge oder eben ein Trennzeichen. 🤡



  • @undertaker
    du missverstehst mich und eventuell auch die sockets ...
    wenn ich angenommen 4 mal schnell hintereinander "pakete" versende
    und beim recv ein wenig langsam bin, liegen praktisch 4 pakete mit einmal im puffer,
    diese würde ich sehr gerne klar voneinander trennen und EVENTUELL auch mit eingebaut haben, das pakete mit falscher längenangabe versendet werden könnten
    ohne das meine übertragung drunter leidet ...
    ich meine damit das manipulierte pakete an mich übertragen werden könnten und ich diese falls sie schlecht manipuliert sind ausfiltern möchte ohne das darauf folgende pakete verstümmelt werden wei ich nur rotz auslese

    @ajaw ja das weis ich das es da kein einfache lösung für gibt eventuell hat sich ber schonmal wer hier gedanken gemacht und was effektiveres als meinen asatz gefunden oder irgendwo mal gelesen ?!

    trennzeichen sind so ne sache, definier mal eins was statistisch selten in einem binären datenstrom auftaucht XD auch da wirst du dich hin und wieder auf die nase legen

    es geht mir drum ich möchte ein kleines netzwerkspiel basteln, das auch tastencombos beinhaltet, der übertragungsaufwand soll dabei minimalistisch sein, jedoch zuverlässig und "regenerativ" bei fehlern. ausserdem sollen die übertragenen strukturen eventuell auch dynamisch sein, ich sag nur chat funktion.



  • falls deine pakete größer werden würd ich dir auf jeden fall raten
    an den anfang jedes pakets einen header zu setzen, der die länge des gesamten pakets enthält.

    andernfalls parst du die daten mehrmals und brichst immerwieder ab weil
    das paket noch nich komplett angekommen is

    was du mit manipulierten paketen meinst versteh ich nich
    tcp stellt ja sicher, dass die daten korrekt bei dir ankommen
    http://de.wikipedia.org/wiki/Transmission_Control_Protocol#Datenintegrit.C3.A4t_und_Zuverl.C3.A4ssigkeit

    oder meinst du dass der sender fehlerhafte daten generiert?



  • Wenn du dich nicht auf korrekte Laengenangaben verlassen kannst, kannst du sie auch gleich weglassen (eben weil du nichtmehr sicher damit arbeiten kannst). Akzeptierst du naemlich einmal eine falsche Angabe, landest du irgendwo im bytestrom, interpretierst irgendwelche Daten als naechste Laenge und stuerzt dich voll ins Gewusel des nonsense.
    In dem Fall waere die einzige moeglichkeit die bleibt entweder eine konstante Paketlaenge oder ein Trennzeichen. Beides hat Vor- und Nachteile:
    - konstante Laenge beschraenkt dich in der Groesse dieser Pakete, ein Trennzeichen reduziert die zur Verfuegung stehenden Zeichen. (Du musst dann evtl. das Zeichen maskieren, wenn es als Teil der Daten gesehen werden soll)
    - bei konstanter Laenge wird bei einfacher Manipulation nur das eine Paket wertlos, beim Trennzeichen koennten zwei Pakete unsinnig werden wenn gerade das Trennzeichen ueberschrieben weird.

    Du solltest entweder sicherstellen dass dir niemand an den Daten rumpfuscht, oder wenns ganz sicher sein und trotzdem flexibel sein soll, versuchs mit Laengenangabe und Testsumme. Wenn die Testsumme der empfangenen Daten nicht stimmt, muesstest du dann allerdings alles verwerfen und dem Sender mitteilen dass du nur Mist empfangen hast.



  • ja, ich habe es schon oft erlebt, das spiele (obwohl meins sicherlich nie so großen andrang bekommt wie die die ich grad meine) von irgendwelchen freaks zerhackt werden, indem sie den datenverkehr mitschneiden, die einzelnen variablen auslesen und dann an einer kritischen stelle ein manipuliertes paket einschleusen um den server zu "verwirren" oder andere dinge auszulösen

    ein beispiel ist ein MMORPG was im moment in der beta phase ist, clientseitig konnte man da zwischen einigen grundlegenden charakter wählen, ein weiterer character war schon serverseitig implementiert aber clientseitig nicht auswählbar, da hat einfach jemand ein manipuliertes paket abgeschickt bei der auswahl wo statt der 5 für den momentan letzten chrarakter eine 6 für den noch versteckten charakter übertragen wurde. und wenn derjenige komplizierte daten manipuliertr kann ihm doch leicht ein fehler unterlaufen, ich möchte aber nicht das die übertragung gleich zusammenbricht deswegen.

    das mit dem header und der länge hab ich oben ja schon grob erklärt und ich dackel im falle eines unvollständigen paketes immer mit msg_peek über den socket und les auch nur so viel wie ich auch brauche, danach such ich wieder den anfang eines neuen paketes usw. oder ich erwarte ein endzeichen, wenn ich selbiges nicht finde geh ich zurück bis zu dem ersten gefundenen header setz dahinter an und such nach einem neuen paket.

    @pumuckl meine übertragung sieht ein startzeichen von 4 byte gefolgt von einem byte oder 2 für die datenlänge vor. trennzeichen sind wurst die können auch zufällig im datenstrom auftauchen und würden zufallsfehler generieren, feste länge wäre ineffizient und auch da kann es passieren das jemand 1 byte zuviel sendet (weil er ja nicht unbedingt weis wie groß 1 paket ist) und dann alle folgepakete verkerht sind.

    das jemand einen fake client baut kann ich nicht oder nur schwer verhindern.

    das mit der prüfsumme könnt ich für das endzeichen verwenden, klasse idee, find ich keins spul ich wie beschrieben zurück und such das nächste startzeichen/paket

    by the way: was wäre ein brauchbares verfahren für ne prüfsumme ?



  • wenn du einfach nur nich willst dass dein spiel zusammenbricht musst du einfach nur die interpretation der daten sehr defensiv programmieren

    d.h. es gibt n nachrichtentypen
    jeder nachrichtentyp hat eine bestimmte länge m
    und jeder wert in dieser nachricht hat einen gültigen wertebereich von x bis y

    und wenn irgendwelche daten ankommen die außerhalb der bereiche liegen
    machst du die verbindung zu, zeigst ne fehlermeldung und springst wieder ins hauptmenü, damit der user ein neues spiel anfangen kann

    @prüfsumme: http://de.wikipedia.org/wiki/Cyclic_Redundancy_Check



  • naja zuuumachen wollt ich nicht gleich, kann ja auch sein das ich irgendwo in der übertragung oder bei der paketgenerierung nen fehler mache und deshalb soll ja eben die verbinndung sich regenerieren ... aber das mit dem CRC iss echt klasse danke _

    damit hätt ich ne doppelte absicherung, einmal gegen falsche datenlänge und gegen "einfache" manipulation.

    gegen einen fake client könnte ich ja noch im falle einer defekten übertragung ein kontrollsignal schicken, wird dieses kontrollsignal nicht vernünftig(also wie von original client erwartet) beantwortet brech ich die verbindung ab.



  • davon auszugehn dass du bei der erstellung oder übertragung nen fehler machst halt ich aber für falsch.

    das wär als würdest du davon ausgehn, dass du auf nen nullpointer zugreifst und dann crasht die software ja auch



  • ja mei, niemand iss perfekt, ich würde versuchen jede eventualität vorherzusehen, aber stell dir einfach mal vor, das du ... was weis ich ... irgend wo nen fehler bei einem befehl geamcht hast, ihn 1 byte länger anlegst als er eigentlich sein soll ... warum auch immer .... du testest den befehl in einer anordnung die funktioniert und irgendein spieler passaiert nun mal worst case er erwischt den befehl und bei ihm stimmen von nun an keine befehle merh, da würde man sich schon wünschen das die verbindung das ausgleicht.

    nen nullpointer kann dir auch überall mal vor die flinte laufen unter testbedingungen passiert nix nachm release schaffts aber n spezialist irgendwie doch n fehler zu prvozieren der SO nicht erwartet war ne Exception halt ... und genau wie try catch möcht ich halt versuchen nen übertragungsfehler vom programm her zu koriigieren



  • da würde man sich schon wünschen das die verbindung das ausgleicht.

    lol auf gar keinen fall



  • netter beitrag .... würdest du mir bitte erläutern warum nicht ?



  • es geht schon... also auch wenns mir nich gefällt is dein ansatz schon möglich
    wenn du fehlerhafte daten findest die nich in dein schema passen wirf sie weg und such nach dem nächsten header



  • @ sovok

    naja ich verbuch das mal unter geschmackssache und über geschmack lässt sich bekanntlich streiten _

    danke jedenfalls, du hast mir auf jeden fall geholfen es noch ein wenig sicherer zu machen



  • sry für doppelpost aber mir ist grad der grund eingefallen wieso ich das mit der regenerierenden verbindung einer defensiven(also reset bei fehler) bevorzuge ... es gibt einige befehle die sich nur unter gewissen umständen, die ein wenig "aufwand" erzeugen, benutzen lassen und um den fehler reprorduzierbar zu machen und eventuell während des auftretens noch debuggen zu können, wollte ich halt das der befehl einfach verworfen wird statt die verbindung zu terminieren.



  • dafür würde aber auch eine gute protokollierung reichen

    wenn die daten verworfen werden hilft dir das auch nicht so sehr beim debuggen


Anmelden zum Antworten