recv: Unbekannte Anzahl Zeichen empfangen
-
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 suchenDanke 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').
-
Wie gross ist receive_buffer
und wie gross ist SOCKET_RECEIVE_BUFFER ???Könnte mir vorstellen, wenn SOCKET_RECEIVE_BUFFER einen zu grossen Wert hat, das dann etwas von den Daten flöten geht ?
Oder wie ? Hä ?
-
So, Problem gelöst, alles was zu tun war, war den receive_buffer und den user_string an den richtigen orten zu terminieren, sowie ein Zeichen weniger von recv zu lesen.
Anschliessend funktioniert das ganze wunderbar.
Vielen Dank für eure Hilfe auf jeden Fall
-
-
btw. würde ich nicht für jedes recv ein realloc aufrufen, weil realloc nun mal sche*ße lahm und potentiell fehleranfällig ist. An deiner Stelle würde ich immer größere Speicher-Blöcke allozieren (2er Potenzen) und dann schauen ob genug Speicher noch übrig ist nach jedem recv und erst dann realloc benutzen (um den nächst größeren Block (2er Potenz) zu allozieren).
Wenn du die Größe des Buffers kennst, dann kannst du auch gleich memcpy nehmen und nicht strcpy
-
rüdiger schrieb:
weil realloc ... potentiell fehleranfällig ist.
Wieso das denn?