recv: Unbekannte Anzahl Zeichen empfangen



  • Hallo,

    in meinem Programm empfange ich eine unbenkannte anzahl Zeichen über das Netzwerk.
    Ich habe mir Gedanken darüber gemacht wie ich diese Daten zwischenspeichern kann, da ich anschliessend den ganzen String auf einmal brauche.

    Ich habe folgende Methode in betracht gezogen:

    do  {
    		nret=recv(theSocket, receive_buffer, SOCKET_RECEIVE_BUFFER, 0);
    		user_string_length = user_string_length + nret;
    		user_string = (char*) realloc(user_string, user_string_length * sizeof(char));
    		if(user_string == NULL){
    			MessageBox(NULL, "Could not allocate enough memory", "Title", MB_OK);
    			return NULL;
    		}
    		strcat(user_string, receive_buffer);
    	} while (nret > 0);
    

    Leider funktioniert das so nicht, erstens erhalte ich immer die Fehlermeldung aus der MessageBox und zweitens werden beim realloc die bereits vorhandenen Daten überschrieben.
    Hat jemand eine Lösung für dieses Problem?

    Danke und Gruss



  • Wird user_string_length irgendwo initialisiert?
    Und wie sorgst du dafür, dass receive_buffer nullterminiert ist? Das ist Voraussetzung, wenn du strcat benutzen willst.



  • user_string_length wird zu beginn auf 0 gesetzt und die einzelnen Blöcke werden auf der Serverseite nullterminiert.



  • dadevelopa schrieb:

    und die einzelnen Blöcke werden auf der Serverseite nullterminiert.

    Und wird dieser Null-Terminator auch mit übertragen? (davon abgesehen ist es durchaus möglich, daß ein am Stück abgeschickter Datenblock für die Übertragung zerlegt und in Einzelteilen empfangen wird)



  • Ja werden sie eigentlich.
    Ich habe das jetzt aber mal entfernt und terminiere die einzelnen Blöcke auf dem Client.
    Trozdem bleibt das Problem mit dem alloziieren von Speicher. Kann es sein das ich beim ersten alloziieren ein malloc brauchen muss?



  • dadevelopa schrieb:

    Ja werden sie eigentlich.
    Ich habe das jetzt aber mal entfernt und terminiere die einzelnen Blöcke auf dem Client.

    Ich weiß nicht, ob das bei dir angekommen ist: Du kannst dich nicht darauf verlassen, dass du auch "Blöcke" empfängst. Es kommt nicht alles, was du in ein send reinsteckst, automatisch aus einem recv raus. Die Daten können gestückelt oder zusammengefasst werden. Daher bringt es wenig, die Daten beim Senden zu terminieren.

    Trozdem bleibt das Problem mit dem alloziieren von Speicher. Kann es sein das ich beim ersten alloziieren ein malloc brauchen muss?

    Nein, nicht wenn du user_string mit NULL initialisiert hast.



  • MFK schrieb:

    Ich weiß nicht, ob das bei dir angekommen ist: Du kannst dich nicht darauf verlassen, dass du auch "Blöcke" empfängst. Es kommt nicht alles, was du in ein send reinsteckst, automatisch aus einem recv raus. Die Daten können gestückelt oder zusammengefasst werden. Daher bringt es wenig, die Daten beim Senden zu terminieren.

    Richtig... darum habe ich ja auch geschrieben das ich nun die Daten auf dem Client terminiere, egal wie sie angekommen sind, eben um strcat benutzen zu können...
    Das funktioniert dank deiner Hilfe nun auch.

    Trozdem bleibt das Alloziierungsproblem. Immer beim zweiten Durchlauf in der Schleife gibt realloc NULL zurürck.



  • Da fällt mir gerade auf: Du alloziierst nicht genug Speicher, die Nullterminierung passt nicht mehr rein. Du brauchst user_string_length + 1 Bytes (oder du initialisiert user_string_length mit 1).

    Außerdem musst du beim ersten Durchlauf den Anfang des Puffers nullterminieren, damit strcat an der richtigen Stelle anhängt.

    Und nebenbei: sizeof(char) ist per Definition 1, den Faktor kannst du weglassen.



  • Ja soweit war ich auch schon 😉

    Na ja ich werde wohl ein wenig weiter experimentieren müssen, ich habe gedacht vielleicht gibts ein unvorhersehbares Verhalten von realloc, dem scheint aber nicht so.
    Muss ich den Fehler hald bei mir selber suchen 😉

    Danke auf jeden Fall für deine schnelle Hilfe.



  • Was ist user_string_length für ein datentyp, vielleicht wirds ja negativ.
    Oder aber, realloc liefert auch NULL, wenn nicht genung Speicher da ist



  • user_string_length ist ein int. Jedoch empfange ich nicht soviele Daten, als das er negativ werden könnte.

    realloc funktioniert perfekt, solange ich keine Daten in die Strings schreibe, sprich, ich kann alle daten empfangen jedoch fehlt mir noch der richtige weg sie abzuspeichern. Irgendwo scheint noch ein Fehler im Code zu sein, jedoch habe ich noch keine Ahnung wo.



  • Hast du denn konsequent die Null-Terminierung der beteiligten Strings beachtet? (zumindest im ersten Schleifendurchlauf liefert realloc() nichts nullterminiertes) Wenn nein, bist du vermutlich munter dabei, die Kontrollstrukturen des Heaps zu pulverisieren.



  • CStoll schrieb:

    Hast du denn konsequent die Null-Terminierung der beteiligten Strings beachtet? (zumindest im ersten Schleifendurchlauf liefert realloc() nichts nullterminiertes) Wenn nein, bist du vermutlich munter dabei, die Kontrollstrukturen des Heaps zu pulverisieren.

    Ja genau das meint mein Debugger auch.
    Folgendes ist mein Code:

    do  {
    		ZeroMemory(receive_buffer, NULL);
    		nret=recv(theSocket, receive_buffer, SOCKET_RECEIVE_BUFFER, 0);
    		user_string_length = user_string_length + nret;
    		user_string = (char*) realloc(user_string, user_string_length + 1);
    
    		if(user_string == NULL){
    			MessageBox(NULL, "Could not allocate enough memory", "Title", MB_OK);
    			return NULL;
    		}
    
    		if(loop_count == 0){
    			user_string[0] = '\0';
    		}
    		strcat(user_string, receive_buffer);
    		user_string[user_string_length] = '\0';
    		loop_count ++ ;
    	} while (nret > 0);
    

    Ich kann beim besten willen nicht sagen wo ich da eine Nullterminierung vergessen habe. Aber ich bin sicher der Fehler ist was kleines und total klar... 😞



  • Ich würde mal sagen, gleich am Anfang 😉 Wenn du realloc() einen NULL-Zeiger übergibst, liefert er dir nicht-initialisierten Speicher - und der ist insbesondere nicht null-terminiert.



  • Ok...

    tut mir leid verstehe ich nicht ganz 😉

    Ich kriege ja Speicher zurück oder etwa nicht?

    Diesen terminiere ich doch dann hier:

    if(loop_count == 0){
      user_string[0] = '\0';
    }
    

    Oder was zum Henker ist denn das?

    Oh man ich muss noch viiiiel lernen; )



  • CStoll schrieb:

    Ich würde mal sagen, gleich am Anfang 😉 Wenn du realloc() einen NULL-Zeiger übergibst, liefert er dir nicht-initialisierten Speicher - und der ist insbesondere nicht null-terminiert.

    Darum hat er wohl auch

    if(loop_count == 0){
                user_string[0] = '\0';
            }
    

    den hier mit reingesetzt. 😉



  • Was sind denn das für Daten, die reinkommen ? Evtl. Binärdateien mit Nullbytes ?



  • Nein eigentlich ein ganz normaler String...



  • Mit deinem ZeroMemory - Parameter sieht das nicht gut aus ( NULL )
    Aber ich glaub das ist es auch nicht, denn der Puffer wird sowieso immer von recv geleert nicht wahr.



  • Und wie groß ist recieve_buffer? recv() nutzt den übergebenen Speicherplatz vollständig aus, also mußt du mindestens ein Byte mehr bereitstellen als du ihm zugestehst (für das abschließende '\0').


Anmelden zum Antworten