Einfaches binäres Protokoll



  • D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste? Oder werden immer ints empfangen? Oder kann man gar bei verschiedenen Bits einstecken?



  • wxSkip schrieb:

    D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste?

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Base64 würde sich z.B. anbieten. Dann könnt ihr Steuerzeichen von Daten eindeutig unterscheiden.

    Was wohl schon wieder länger wäre als die ASCII-Darstellung.



  • Hm das mit der Base64 kodierung sieht ziemlich kompliziert aus...
    Aber falls es da was gutes fertiges zu gibt, würde das natürlich gehen.

    Evtl. ignorier ich das Problem auch einfach, weil die Wahrscheinlichkeit relativ gering ist, oder ich überprüf vorm senden, ob ich was problematisches sende und wenn ja, passe ich es minimal an.

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    Weitere Vorschläge sind natürlich trotzdem willkommen.



  • Q schrieb:

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    cooky451 schrieb:

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Das LZ77 guck ich mir gleich an, aber dazu muss ich folgendes sagen:
    Ich kenne LZW und vermute, dass das so ähnlich ist.
    Da wird nach und nach ein Wörterbuch aufgebaut, was hier aber nicht praktikabel ist, weil man zu jedem Zeitpunkt sich einklinken kann.
    Außerdem muss man wenn man sich zu jedem Zeitpunkt einklinken kann trotz kompression den "Anfang" finden (der früher nach dem ersten \n los ging).
    Ich hoffe mal, dass das damit möglich ist.



  • Wenn ihr ein bisschen Rechenzeit für binäre Operationen übrig habt, könnt ihr ja auch einfach je nach Datenpaket abwechselnd eine 1 und eine 0 ins High-Bit jedes chars setzen - und die anderen 7 Bits für die Codierung nutzen. Dann nehmt ihr halt 5 chars statt 4 für eine 32-bit-Zahl und lasst die restlichen 3 Bit leer oder wenn die euch reichen, schreibt ihr dort den Typ rein (int, unsigned int, float, ...).



  • 1. Falls man das Ding zu jedem Zeitpunkt reinstecken kann und die vorherigen Daten eh egal sind, kann man die Synchronisierung auch sehr viel später machen.
    Einmal pro Sekunde, einmal pro Minute, wie auch immer.

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.



  • nurf schrieb:

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.

    Nö. Es könnte ja sein, dass zufällig 4 Input-Werte à 4 Bytes ankommen, die zusammen genau den Magic String ergeben. Außer, du willst nach jedem Input-Wert den Magic-String senden. Dann ist es aber mit der Ersparnis dahin.



  • Ein Vorschlag ohne den ganzen Thread gelesen zu haben.

    Q schrieb:

    2003 3 iff XXXX XXXX XXXX 2058

    • Du startest jede Übertragung mit vier Einsen (Praembel): 1111. Wenn du das bekommst, geht eine Übertragung los.
    • Danach kommt ein Wechsel auf 0 als Startbit um einzuleiten, dass die Typinformationen kommen.
    • Anschließend folgt deine Typcodierung. Hier muss ich aber von dir erfahren, wieviele Typen du haben kannst. Vielleicht kann man dort die Anzahl und die Typen zusammen kodieren.
    • Jetzt das interessante. Du benutzt folgende Codierung. Eine 1 als 10 und eine 0 als 01. ZB ist die Zahle 5 = 0101 in dieser Kodierung (habe vergessen wie diese heißt) = 01100110. Mit dieser Kodierung wirst du nie mehr als zwei aufeinanderfolgende Einsen bzw Nullen haben. Dh, dort werden nie vier 1 wie im Praembel erscheinen. Also sollte das Praembel mindestens drei gleiche Bits haben, wieso ich vier habe, habe ich dummerweise waehrend des Schreibens vergessen 🙂 Da war irgendwas mit Startbit und Typkodierung.

    Somit werden vier Einsen - jetzt weiß ich auch wieso, weil ich im Kopf hatte die Typen als drei Bit zu kodieren und da 111 drin sein könnte, aber dafür brauche ich ja ehe noch Informationen von dir - nie in deinem Daten vorkommen. Du musst dann von den reinen Daten doppelt soviel Übertragen, wie du gern haettest, aber vllt stört dich das ja nicht.

    Wenn du den Stecker mittendrin einsteckst, wartest du einfach auf die vier Einsen. Und stell dir mal vor du würdest das Startbit (0) nicht haben, und bei der letzten Praembel-1 einstecken und dann würden nochmal drei Einsen wegen des Types kommen und du würdest das als Praembel dann faelschlicherweise interpretieren. Aber genau dafür ist der Wechsel auf 0 da. Also einfach auf vier Einsen und dann den Wechsel auf 0 warten und du weißt, dass es jetzt startet.

    Edit: Manchester-Codierung war es 🙂



  • Nö. Es könnte ja sein, dass zufällig 4 Input-Werte à 4 Bytes ankommen, die zusammen genau den Magic String ergeben.

    Mit ner Chance von 340282366920938463463374607431768211456 (2^128) zu 1.



  • Du könntest Folgendes tun:
    Du kodierst deine Daten ganz normal mit Kontrollzeichen, die angeben wann ein Block anfängt, wie lang er ist, welchen Typ deine Daten haben etc..
    Danach schickst du deine Daten durch eine Funktion, die folgendes tut (ungetestet):

    EDIT:
    Hab gar nicht erklärt was ich machen würde... also:
    Man entfernt aus allen Bytes das unterste Bit. Diese Bits von 7 Bytes speichert man dann nebeneinander in einem 8. Byte (von oben beginnend, damit das unterste Bit aus ist) und macht die low bits in den ursprünglichen Daten aus. Alle Bytes haben jetzt das unterste Bit nicht gesetzt. Man kann deshalb ab und zu (vor jedem Block, alle x Sekunden, whatever) einmal einen Wert mit gesetztem low bit (z.B. 255) senden, der dir dann als Einstiegspunkt zum parsen eines binären Formats dienen kann. Der Platzverbraucht steigt dadurch (je nach Häufkigkeit der Synchro-Punkte) um 14% - 28% an.
    /EDIT

    void übertrage_sieben_byte( unsigned char *Input)
    {
        unsigned char transformed_data[8];  //das wird nachher übertragen
        unsigned char &low_bits = transformed_data[7];  //hier kommt von den 7 Bytes jeweils das unterste Bit rein
        low_bits = 0; //kein Bit an
        for( unsigned int i=0; i<7 ; ++i )
        {
            unsigned char current_low_bit = Input[i] & 1; //untesters Bit holen
            transformed_data[ i ] = Input[i] & 254 ; //alle Bits bleiben wie sie sind, nur das unterste wird ausgemacht
            low_bits = low_bits | ( current_low_bit << ( 7 - i ) ) ; //beginnend links wird jeweils das unterste Bit in low_bits geschrieben
        }
    
        send( transformed_data );
    }
    

    Vor jedem Block machst du dann

    void neuer_block()
    {
        unsigned char magic_number = 255; //alle Bits an, auch das letzte
        send( magic_number );
    }
    

    Als Empfänger wartest du dann auf 255, danach kannst du dir jeweils 7 Bytes rekonstruieren, indem du die low_bits aus dem 8 Byte unten dranklebst.

    Bin verdammt müde, hoffe das ist kein murks.


Anmelden zum Antworten