Sehr langer String



  • build schrieb:

    Was passiert den in diesem Fall? Wäre dies dann die Nullterminierung, so dass ich die nachfolgenden Zeichen vergessen kann (da operator += bis \0 durchläuft)?

    Ja.
    deshalb:
    str_rec.append(strDataBuffer, bytes_rec);

    wobei es natuerlich besser waere das ganze ohne kopieren zu machen.
    Und nebenbei bemerkt: du checkst nicht auf Fehler beim recvfrom.



  • build schrieb:

    Was passiert den in diesem Fall? Wäre dies dann die Nullterminierung, so dass ich die nachfolgenden Zeichen vergessen kann (da operator += bis \0 durchläuft)?

    Ja. Bzw: Ich glaube, es gibt gar keinen operator += (char const*), sondern nur einen operator += (string), bei dem die implizite Konvertierung über den Konvertierungs-Ctor greift. Aber für den Code ist das letztendlich egal.



  • Kellerautomat schrieb:

    Ich glaube, es gibt gar keinen operator += (char const*)

    doch.
    das ist std::string.
    da gibts alles.

    in manchen Implementierungen gibts auch eine koche_kaffee() Funktion.



  • Ich bin jetzt soweit:

    #define MAX_PACKET_SIZE 1024
    .
    .
    .
    	char	strDataBuffer[MAX_PACKET_SIZE]; // Unsere Daten
    
    	// Alle Pakete empfangen
    	size_t bytes_rec = 0;
    	size_t bytes_recv_total = 0;
    	std::string str_rec;
    	std::list<std::string> str_list;
    
    	do
    	{
    		memset(strDataBuffer, 0, MAX_PACKET_SIZE);
    		bytes_rec = recvfrom(_sock, strDataBuffer, MAX_PACKET_SIZE, 0, 0, 0);
    
    		// Alles gut gelaufen?
    		if(bytes_rec == SOCKET_ERROR)
    			return; // Na toll, ein Fehler
    
    		str_rec.append(strDataBuffer);
    
    		// Bei zuvielen Zeichen, den aktuellen String in eine Liste einfuegen
    		// Danach leeren
    		if(str_rec.length() >= str_rec.max_size()-MAX_PACKET_SIZE) 
    		{
    			str_list.push_back(str_rec);	// Hinten anfügen
    			str_rec.clear();			
    		}
    
    		bytes_recv_total += bytes_rec;
    	}
    	while(bytes_rec != 0);
    

    Jetzt bin ich soweit, dass ich aus diesen vielen Teilstrings einen großen CString erstellen möchte.
    Deshalb würde dieser Ansatz gehen?

    char *buffer = new char[bytes_rec];	// Ausgabepuffer
    	memset(buffer, 0, bytes_rec);
    
    	for(std::list<std::string>::const_iterator it = str_list.begin(); it != str_list.end(); it++)
    	{
    		sprintf(buffer, "%s%s", buffer, it->c_str());
    	}
    


  • str_rec.append(strDataBuffer);

    da hast du immernoch das selbe Problem.



  • Habs jetzt so gelöst und es funktioniert zumindest teilweise:

    for(int i = 0; i < MAX_PACKET_SIZE; i++)
    	str_rec += strDataBuffer[i];
    

    Bei Textdateien funktioniert dies wunderbar. Bei einem 4MB großen Bild, bekomme ich 1,5KB zuviel. Kann dies immernoch am operator+= liegen?



  • build schrieb:

    for(int i = 0; i < MAX_PACKET_SIZE; i++)
    	str_rec += strDataBuffer[i];
    

    Ich habe dir die Lösung doch schon gepostet:

    str_rec.append(strDataBuffer, bytes_rec);

    Bei deiner Schleife hast du nämlich das Problem: was passiert wenn du weniger als MAX_PACKET_SIZE an Daten bekommst? Dann füllst du mit 0 auf. Und das könnte zB deine 1,5k zuviel sein.



  • Oh das habe ich komplett übersehen. Deswegen hier ein verspätetes Danke!
    Und was ist in dem Fall, wie du beschrieben hast, dass die Datei den char-Wert 0 enthält? Den meine Dateien sind zwar gleich groß, haben aber die md5 Summen stimmen nicht überein.



  • build schrieb:

    Oh das habe ich komplett übersehen. Deswegen hier ein verspätetes Danke!
    Und was ist in dem Fall, wie du beschrieben hast, dass die Datei den char-Wert 0 enthält? Den meine Dateien sind zwar gleich groß, haben aber die md5 Summen stimmen nicht überein.

    std::string kann 0 werte enthalten. Die Frage ist, wie du die Daten dann in die Datei schreibst.

    Kommen denn die richtigen Anzahl Bytes jetzt an?



  • Ja die angekommenen Byte passen mit den gesendeten (und der Originaldatei) überein.
    Das Reinschreiben übernimmt die fstream.

    // pb.pData->data sind die durch recv erhaltenen Daten
    // pb.pData->nlength sind die durch recv erhaltenen Anzahl an Bytes des Datensatzes
    std::fstream file(filename, std::ios::out | std::ios::binary);
    
    file.write(pb.pData->data, pb.pData->nlength);
    
    file.close();
    


  • Und wie bekommst du pData->data?
    Da muss ja wieder irgendwo was kopiert werden.

    Hast du auch die Dateien korrekt als binary geöffnet und nicht als Text?



  • Datei öffnen:

    /** Unsere eigentlichen Daten */
    struct PacketTransmission
    {
    	char *data;			// Daten an sich
    	size_t nlength;			// Dateigroeße
    };
    
    FILE *fp = fopen(pb.filename.c_str(), "rb");
    
    // Dateigroese herausbekommen
    fseek(fp, 0, SEEK_END);
    int length = ftell(fp);
    rewind(fp);
    
    if(pb.pData == NULL)
    	pb.pData = new PacketTransmission;
    
    pb.pData->nlength = length;
    
    pb.pData->data = new char[length];
    
    fread(pb.pData->data, length, 1, fp);
    
    fclose(fp);
    

    Setzen eines Strings

    void Packet::SetString(std::string strData)
    {
    	if(pb.pData == NULL)
    	{
    		pb.pData = new PacketTransmission;
    		pb.pData->data = NULL;
    	}
    
    	if(pb.pData->data == NULL)
    	{
    		pb.pData->data = new char[strData.length()];
    		pb.pData->nlength = strData.length();
    		strcpy(pb.pData->data, strData.c_str());
    	}
    	else
    	{
    		delete pb.pData->data;
    
    		pb.pData->data = new char[strData.length()];
    		pb.pData->nlength = strData.length();
    		strcpy(pb.pData->data, strData.c_str());
    	}
    }
    

    Kann es sein, dass es daran liegt, dass ich nur ein send hab, welches mehrere MB rüberschickt und dadurch Unmengen an Fehler entstehen können?



  • strcpy(pb.pData->data, strData.c_str());

    hier hast du wieder das Problem mit den 0 Bytes.
    du brauchst hier memcpy

    Das Problem ist, du hast keinen echten C String. Ein C String ist nämlich dadurch definiert, dass er mit einem 0 Byte beendet wird. Wenn du binärdaten überträgst ist das aber nicht gegeben und du musst immer die größe mitangeben.

    Warum mischst du C und C++ eigentlich so?

    PS:
    delete pb.pData->data;
    das muss
    delete [] pb.pData->data;
    lauten.



  • Shade Of Mine schrieb:

    strcpy(pb.pData->data, strData.c_str());

    hier hast du wieder das Problem mit den 0 Bytes.
    du brauchst hier memcpy

    Das Problem ist, du hast keinen echten C String. Ein C String ist nämlich dadurch definiert, dass er mit einem 0 Byte beendet wird. Wenn du binärdaten überträgst ist das aber nicht gegeben und du musst immer die größe mitangeben.

    Warum mischst du C und C++ eigentlich so?

    PS:
    delete pb.pData->data;
    das muss
    delete [] pb.pData->data;
    lauten.

    Ah nochmal ein sehr sehr großes Danke! Endlich funktioniert es!
    Das Vermischen ist eig. im Nachhinein enstanden, da ich anfangs nur C++ genutzt habe und testen wollte, ob es evtl. am fstream / string lag.

    MD5 stimmt jetzt auch komplett überein.

    Nochmal ein großer Dank an alle!


Anmelden zum Antworten