Dynamisches char im struct



  • Einen Fehler gibt mein recvfrom nicht zurück. Übrigens fange ich natürlich dort immer die Fehler ab, aber der Code sollte nicht zulang werden. Trotzdem danke für den Hinweis!
    read hatte ich schonmal getestet ohne das sich was geändert hat. 😞
    Die socket-Methode habe ich auch so schon getestet, ohne Veränderung. 😞

    Die maximale Größe kenne ich nicht wirklich, aber die Größen bewegen sich im Bereich von 1000-1500. Mehr als 2000 ist es auf jeden Fall nie. Da kann man die Größe ja einfach groß genung wählen z.B. 2000.

    Wie das dann aber funktionieren soll weiß ich trotzdem nicht und hoffe da nochmal auf deine Mithilfe. Soweit schonmal vielen Dank!



  • jox schrieb:

    recvfrom(s, &test.zahl, sizeof(test.zahl), 0, 0, 0);
    

    man muss den rückgabewert von recv checken. ist der grösser 0 aber kleiner als die ses 'sizeof(test.zahl)' dann wurde nur ein teil empfangen. in diesem fall also recv wiederholt aufrufen bis man alles hat.



  • Der erste Teil (eine Zahl) wird doch auch korrekt empfangen. Gerade das wiederholte aufrufen von recv klappt ja nicht, weil dann das nächste empangene Paket genommen wird und nicht das 'alte' aus dem der Rest gelesen werden soll.



  • germangeek schrieb:

    Der erste Teil (eine Zahl) wird doch auch korrekt empfangen. Gerade das wiederholte aufrufen von recv klappt ja nicht, weil dann das nächste empangene Paket genommen wird und nicht das 'alte' aus dem der Rest gelesen werden soll.

    dann benutzt du udp (datagramme) und nicht tcp (stream)?



  • jup, ganz genau. Ich hätte nicht erwartet, dass das einen Unterschied macht.



  • germangeek schrieb:

    jup, ganz genau. Ich hätte nicht erwartet, dass das einen Unterschied macht.

    einen gewaltigen unterschied macht das. tcp schiebt alles empfangene in einen FIFO aus dem der user sich das häppchenweise holen kann. bei udp bekommste pakete und wenn man nicht alles abholt ist der rest weg. guckst du: http://www.c-worker.ch/tuts/udp.html



  • Verdammt! Ich muss an der Stelle leider bei UDP bleiben.
    Gibt ess eine Möglichkeit das zu umgehen? Ansonsten hoffe ich ja noch auf jox mit einer genialen Lösung 🙂



  • mach ein recv oder recvfrom unter angabe der vollen länge:

    unsigned char buffer[1500];
    ...
    recv_result = recv (socket, buffer, sizeof(buffer), 0);
    ...
    

    dann haste alle daten.



  • Ich bekomme ja nun aber gerade einen struct geschickt! In diesem stehen am Anfang mehrere Zahlen, dann kann ich doch nicht einfach alles in einen char schreiben, oder doch?



  • struct data *test = (struct data*) buffer;
    printf("Laenge der Daten: %d\n", test->laenge);
    

    😉



  • Da gibt aber den Fehler:

    error: dereferencing pointer to incomplete type



  • germangeek schrieb:

    Ich bekomme ja nun aber gerade einen struct geschickt! In diesem stehen am Anfang mehrere Zahlen, dann kann ich doch nicht einfach alles in einen char schreiben, oder doch?

    Doch, würde ich so auch versuchen. Einfach einen Buffer mit der maximalen Länge vorsehen und dann alles einlesen:

    unsigned char buffer[MAX_LENGTH];
    struct data *test;
    
    rc = recvfrom(s, buffer, sizeof(buffer), 0, 0, 0);
    
    test = (struct data *) buffer;
    
    if (rc < (sizeof(test->zahl)+sizeof(test->zahl2)+sizeof(test->laenge)) => Error
    else if (rc != (test->laenge+sizeof(test->zahl)+sizeof(test->zahl2)+sizeof(test->laenge))) => Error
    else => alles korrekt empfangen
    ...
    

    Aber Achtung: UDP ist ein ungesichertes Protokoll. Es ist nicht sichergestellt, dass alle Daten rüberkommen! Deswegen der Vergleich: "rc != test->laenge"



  • germangeek schrieb:

    Ich bekomme ja nun aber gerade einen struct geschickt! In diesem stehen am Anfang mehrere Zahlen, dann kann ich doch nicht einfach alles in einen char schreiben, oder doch?

    das geht (im idealfall so wie lordJax vorschlägt, aber unter vorbehalt, gleicher compiler, gleiche architektur auf beiden seiten usw.). rückgabewert von recv ist dann die paketlänge (also alle struct members und der datenblock)



  • jox schrieb:

    Aber Achtung: UDP ist ein ungesichertes Protokoll. Es ist nicht sichergestellt, dass alle Daten rüberkommen! Deswegen der Vergleich: "rc != test->laenge"

    nee, wenn das paket ankommt dann ist alles in ordnung. man braucht z.b. keinen crc anhängen oder ähnliches. was passieren kann ist, dass pakete ganz ausbleiben (entweder sie schafften's nicht über's netz oder wurden von lokalen komponenten weggeschmissen wegen negativen integritäts-checks)



  • Okay, dann noch zwei (hoffentlich) letzt Fragen:
    1.) Warum gibt es in test = (struct data 😉 buffer; den Fehler:

    error: incompatible types in assignment

    EDIT: 1.) hat sich erledigt. Mein Fehler!

    2.) Wie bekomme ich es dann hin, dass meine struktur wieder korrekt ist?
    Ich lege mir einen neuen struct data an und kopiere die int's rüber. Wie aber läuft das mit dem char? Das 'echte' char ist ja kleiner als es aktuell im buffer drin liegt!



  • Wieso musst Du die Struct nochmal kopieren? Nimm test, welches auf Buffer zeigt, und gut ist.

    Die Daten hinten kannst Du auch mit daten[16] ansprechen, lass Dich nicht davon irritieren, dass die vermeintliche Länge nur 1 ist.



  • germangeek schrieb:

    2.) Wie bekomme ich es dann hin, dass meine struktur wieder korrekt ist?
    Ich lege mir einen neuen struct data an und kopiere die int's rüber. Wie aber läuft das mit dem char? Das 'echte' char ist ja kleiner als es aktuell im buffer drin liegt!

    Du brauchst die Strukturelemente nicht zu kopieren, lasse einfach Deine Struktur auf den Anfang des Buffers zeigen (siehe mein Code-Beispiel oben). char[1] ist nur ein "Platzhalter". Du kannst auf die einzelnen Elemente des Array anschließend normal auch mit Indices >0 zugreifen.



  • Wie geben ich denn jetzt z.B. die zahlen aus?
    Jetzt bin ich verwirrt...

    printf("Laenge der Daten: %d\n", test->laenge)
    So geht es nämlich nicht.



  • germangeek schrieb:

    2.) Wie bekomme ich es dann hin, dass meine struktur wieder korrekt ist?

    ich finde du solltest von diesem struct trip runterkommen. definier' dein paketformat als eine folge von 'octets' z.b.

    anzahl | bedeutung
    2        blubb
    2        blah
    2        länge des datenblocks
    0..x     datenblock
    

    ...und dann legste noch die byte order fest (little endian wär sinnvoll für x86 kisten)
    damit gehste vielen problemen aus dem weg 😉



  • Doch, genau so.

    (Tipp: "Geht nicht" ist keine ausreichende Fehlerbeschreibung)


Anmelden zum Antworten