Binärdaten über Sockets empfangen?



  • Hey,
    wie der Titel schon sagt arbeite ich an einem einfachen HTTP 1.0 Client, habe aber Probleme mit Binärdaten. Textdateien lassen sich einfach über

    do {
            count = recv( sock, buffer, sizeof(buffer), 0);
    		strcat(content, buffer);
        }
        while (count > 0);
    

    empfangen.
    Wenn ich aber nun z.B. ein PNG anfordere und in eine Datei schreibe, ist diese nicht lesbar.
    Kann mir pls jmd helfen? 🙂



  • Autsch. Dein Code zeigt einfach, dass du Stringhandling in C nicht verstanden hast. In C sind Strings mit 0-terminiert. strcat etc. arbeitet mit Strings. Aber recv liefert keine 0-terminierten Strings! Du bekommst einfach die Daten wie sie empfangen wurden und über den Rückgabewert die Anzahl der Bytes.

    Du kannst hier kein strcat nehmen! Aber es ist noch schlimmer. strcat führt keinerlei Überprüfung von Buffergrößen durch. Es wäre also ein leichtes den content Buffer überlaufen zu lassen.

    Und strcat ist auch der Grund, warum es mit Binärdaten nicht klappt. Binärdaten können nämlich 0en enthalten.

    Ich hoffe, dass das kein Produktivcode werden soll. Nimm dann lieber etwas fertiges (zB libcurl).



  • Danke für die Erklärung, das hat mich schon deutlich weiter gebracht.
    Nein, das sollte keine Produktivsoftware werden, da würd ich mich ja zum Obst der Woche machn 😉
    libcurl hatt ich mich schonmal mit beschäftigt, gefällt mir aber iwie nich so. Was hältst du von libwww?



  • Solange du C nicht verstanden hast hilft dir auch keine lib. Versuche einfach mal das vernünftig zu machen, wenn du C dann kannst, kannst du immer noch libcurl nutzen auf C++ umsteigen. 😉



  • Statt strcat memcpy benutzen.
    Ist aber nix für 'nen Anfänger. Sonst kracht's recht schnell.



  • Kannst du bitte erläutern, wie du das mit memcpy machen würdest?



  • char *m_data;
    int m_data_size, m_buf_size;
    
    bool CCharBuffer::AppendData( char *p, int amount )
    {
    	if( !p || amount < 0 )
    		return( false );
    	size_t uamount = static_cast<size_t> ( amount );
    	if( m_data_size+amount < m_buf_size )
    	{
    		memcpy(m_data+m_data_size, p, uamount);
    		m_data[m_data_size+amount] = 0;
    	}
    	else
    	{
    		char *tmp = new char[m_data_size+amount+1];
    		if( !tmp )
    		{
    			return( false );
    		}
    		memcpy(tmp, m_data, m_data_size);
    		delete [] m_data;
    		memcpy(tmp+m_data_size, p, uamount);
    		tmp[m_data_size+amount] = 0;
    		m_data = tmp;
    		m_buf_size = m_data_size+amount+1;
    	}
    	m_data_size += amount;
    	return( true );
    } // bool CCharBuffer::AppendData( char *p, int amount )
    


  • EOP schrieb:

    char *m_data;
    int m_data_size, m_buf_size;
    
    bool CCharBuffer::AppendData( char *p, int amount )
    {
    	if( !p || amount < 0 )
    		return( false );
    	size_t uamount = static_cast<size_t> ( amount );
    	if( m_data_size+amount < m_buf_size )
    	{
    		memcpy(m_data+m_data_size, p, uamount);
    		m_data[m_data_size+amount] = 0;
    	}
    	else
    	{
    		char *tmp = new char[m_data_size+amount+1];
    		if( !tmp )
    		{
    			return( false );
    		}
    		memcpy(tmp, m_data, m_data_size);
    		delete [] m_data;
    		memcpy(tmp+m_data_size, p, uamount);
    		tmp[m_data_size+amount] = 0;
    		m_data = tmp;
    		m_buf_size = m_data_size+amount+1;
    	}
    	m_data_size += amount;
    	return( true );
    } // bool CCharBuffer::AppendData( char *p, int amount )
    

    Wo hast du diese Scheiße denn ausgegraben?



  • TyRoXx schrieb:

    EOP schrieb:

    char *m_data;
    ...
    

    Wo hast du diese Scheiße denn ausgegraben?

    Was hast du da dran auszusetzen?

    Komm mir jetzt bloß nicht mit vector<char>. Das ist was für Mädchen.
    Es ging darum wie man memcpy benutzt und um dem OP zu zeigen, daß man sich Größen und Positionen merken muss.



  • EOP schrieb:

    TyRoXx schrieb:

    EOP schrieb:

    char *m_data;
    ...
    

    Wo hast du diese Scheiße denn ausgegraben?

    Was hast du da dran auszusetzen?

    Komm mir jetzt bloß nicht mit vector<char>. Das ist was für Mädchen.
    Es ging darum wie man memcpy benutzt und um dem OP zu zeigen, daß man sich Größen und Positionen merken muss.

    Ich glaube hier geht es um C, also kommt vector nicht direkt in Frage. Das heißt aber nicht, dass man unterirdisches C mit Klassen propagieren muss.

    bool //schon mal was von Ausnahmen gehört?
    CCharBuffer //eine hässliche Unart
    ::AppendData( char *p, //const fehlt, p ist kein vernünftiger Name
    	int amount ) //warum denn int?
    {
        if( !p || amount < 0 ) //assert(..), und warum nicht einfach size_t?
            return( false ); //überflüssige und falsch gesetzte Klammern
        size_t uamount = static_cast<size_t> ( amount ); //jetzt auf einmal doch size_t
        if( m_data_size+amount < m_buf_size ) //das könnte man einfacher haben mit vector<char>
        {
            memcpy(m_data+m_data_size, p, uamount);
            m_data[m_data_size+amount] = 0; //wieso das denn? Müsste die Klasse dann nicht CString heißen?
        }
        else
        {
            char *tmp = new char[m_data_size+amount+1]; //aua
            if( !tmp ) //new gibt nicht 0 zurück
            {
                return( false );
            }
            memcpy(tmp, m_data, m_data_size);
            delete [] m_data;
            memcpy(tmp+m_data_size, p, uamount);
            tmp[m_data_size+amount] = 0;
            m_data = tmp;
            m_buf_size = m_data_size+amount+1; //die drei Summanden hatten wir eben schon bei new[]
        }
        m_data_size += amount;
        return( true );
    } // bool CCharBuffer::AppendData( char *p, int amount )
    


  • int amount ) //warum denn int?

    Weil recv einen int liefert.

    char *tmp = new char[m_data_size+amount+1]; //aua

    Was ist hier denn schon wieder aua?

    if( !tmp ) //new gibt nicht 0 zurück

    Die Kritik daran hab ich erwartet und akzeptiere ich.

    Ansonsten schreibe ich seit über 20 Jahren Programme, die auch ohne exceptions fehlerfrei funktionieren.

    Problem war: ich musste in einem download beliebiger Größe nach mehreren Schlüsselwörtern suchen:
    - Download nach Schlüsselwort durchsuchen
    - wenn Schlüsselwort nicht gefunden, download - (Länge des längsten Schlüsselworts - 1) speichern und weiter

    Und wie würde ich einen vector<char> nach Schlüsselwörtern durchsuchen?



  • EOP schrieb:

    int amount ) //warum denn int?

    Weil recv einen int liefert.

    Was hat recv denn mit CCharBuffer zu tun? Genau, gar nichts!

    EOP schrieb:

    char *tmp = new char[m_data_size+amount+1]; //aua

    Was ist hier denn schon wieder aua?

    Dein Steinzeit-Compiler kennt anscheinend vector nicht oder du bist noch verkalkter als jener.

    EOP schrieb:

    if( !tmp ) //new gibt nicht 0 zurück

    Die Kritik daran hab ich erwartet und akzeptiere ich.

    .. wenn nackte Tatsachen nichts mehr ausrichten können.

    EOP schrieb:

    Ansonsten schreibe ich seit über 20 Jahren Programme, die auch ohne exceptions fehlerfrei funktionieren.

    Das ist jetzt nicht dein Ernst, oder?

    EOP schrieb:

    Und wie würde ich einen vector<char> nach Schlüsselwörtern durchsuchen?

    Das ist nicht mehr komisch, du kannst aufhören.



  • Was bist du denn für ein Depp? Nur Gemecker aber nix Konstruktives von dir. Absolut nix.

    Und wie würde ich einen vector<char> nach Schlüsselwörtern durchsuchen?

    Antworte bitte.



  • In C gibt es weder vector<char> noch new char[...]. Also wenn du Fragen zu vector<char> hast, dann stell sie bitte im C++-Forum. Die ganze Diskussion ist sicher wenig hilfreich für den Op.



  • rüdiger schrieb:

    In C gibt es weder vector<char> noch new char[...]. Also wenn du Fragen zu vector<char> hast, dann stell sie bitte im C++-Forum. Die ganze Diskussion ist sicher wenig hilfreich für den Op.

    Dann nimm eben malloc und free.



  • EOP schrieb:

    rüdiger schrieb:

    In C gibt es weder vector<char> noch new char[...]. Also wenn du Fragen zu vector<char> hast, dann stell sie bitte im C++-Forum. Die ganze Diskussion ist sicher wenig hilfreich für den Op.

    Dann nimm eben malloc und free.

    realloc. Aber selbst dann hat dein Code noch die angesprochenen Probleme und vorallem auch eine schlechte Allokierungsstrategie. Sobald du einmal die Kapazität erreicht hast, hast du dann ein realloc pro recv!



  • rüdiger schrieb:

    EOP schrieb:

    rüdiger schrieb:

    In C gibt es weder vector<char> noch new char[...]. Also wenn du Fragen zu vector<char> hast, dann stell sie bitte im C++-Forum. Die ganze Diskussion ist sicher wenig hilfreich für den Op.

    Dann nimm eben malloc und free.

    realloc. Aber selbst dann hat dein Code noch die angesprochenen Probleme und vorallem auch eine schlechte Allokierungsstrategie. Sobald du einmal die Kapazität erreicht hast, hast du dann ein realloc pro recv!

    Das war ja nur ein Teil einer Klasse um irgendeine binäre Geschichte zu lösen.

    Sobald keins der Schlüsselwörter gefunden wurde, wird der Puffer (minus Länge des längsten Schlüsselworts - 1) geschrieben, Rest an den Anfang verschoben und wiederverwendet.
    Nix mit ständigem realloc.

    Außerdem lese ich nie mehr als der Puffer groß ist. Da gibt's höchstens am Anfang mal ein "realloc".
    Würde ich den Puffer von Anfang an mit (Größe x + Länge des längsten Schlüsselworts) allozieren und nur immer Größe x lesen, gäb's eigentlich nie ein realloc.



  • EOP schrieb:

    Und wie würde ich einen vector<char> nach Schlüsselwörtern durchsuchen?

    Ist das deine Vorstellung von seit 20 Jahren programmieren? 😮
    Egal wie du vorher nach Schlüsselwörtern gesucht hast, mit dem vector wird es letztlich genau so funktionieren.

    @TE
    Eine einfache Möglichkeit ist, den empfangenen Puffer immer gleich in eine Datei zu schreiben. Dann musst du dich um das malloc/realloc Gefrickel nicht kümmern.



  • BlackCubeX schrieb:

    Hey,
    wie der Titel schon sagt arbeite ich an einem einfachen HTTP 1.0 Client, habe aber Probleme mit Binärdaten. Textdateien lassen sich einfach über

    do {
            count = recv( sock, buffer, sizeof(buffer), 0);
    		strcat(content, buffer);
        }
        while (count > 0);
    

    empfangen.
    Wenn ich aber nun z.B. ein PNG anfordere und in eine Datei schreibe, ist diese nicht lesbar.

    Wie du schon richtig erkannt hast, kann das für Binärdateien nicht funktionieren, da strcat verwendet wird, was nur Strings richtig verarbeitet.

    unsigned char buffer[1024],*b=0;
    size_t p=0;
    while( (count = recv( sock, buffer, 1024, 0))>0 )
    {
      b=realloc(b,p+count);
      memcpy(b+p,buffer,count);
      p+=count;
    }
    


  • cooky451 schrieb:

    EOP schrieb:

    Und wie würde ich einen vector<char> nach Schlüsselwörtern durchsuchen?

    Ist das deine Vorstellung von seit 20 Jahren programmieren? 😮

    Das ist nicht meine Vorstellung sondern die Realität.

    Außerdem liebe ich memcpy, memmove, etc. 😋


Anmelden zum Antworten