Datei runterladen

Schnelle objektorientierte, kompilierende Programmiersprache.
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Datei runterladen

Beitrag von Xin » Fr Jul 06, 2012 7:07 am

Kmitska hat geschrieben:Habe das nun so gemacht:

Code: Alles auswählen

  char* gesamt = new char[30308];
Woher hast Du diese Zahl?

Ich spare uns mal die quote-Tags:

Code: Alles auswählen

    for(int i=0; i<=(30308/1024); i++){
        sock.recv(*antwort);
        strcat(gesamt, antwort);
    }
Wieso legst Du Deine Klasse offenbar auf 1024 Bytes aus?

Code: Alles auswählen

    ofstream file("image.png");
    file << gesamt;
Das ist Unsinn.

Du stellst eine HTTP-Anfrage und bekommst eine HTTP-Antwort, die das Bild enthalten könnte, aber nicht muss!
Ob das Bild drin ist - und wie groß es ist - steht in der HTTP-Antwort.
Kmitska hat geschrieben:Was könnte da schief gehen? :/
Ich habe Dich vor wenigen Tagen erst aufgefordert, Dir HTTP auf Wikipedia durchzulesen und dass ich Dir das nicht einzeln vorkauen kann. Das hast Du offensichtlich nicht getan.
Ich bin derzeit nicht sicher, wieviel Aufwand für eine Antwort sinnvoll ist, wenn Du sie dann nicht beachtest.
Du bekommt also erneut die gleiche Antwort: Lies Dir durch, wie HTTP funktioniert.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Re: Datei runterladen

Beitrag von Kmitska » Fr Jul 06, 2012 7:55 pm

Woher hast Du diese Zahl?
Das ist die Länge, den ich aus dem Header erhalte.
Wieso legst Du Deine Klasse offenbar auf 1024 Bytes aus?
Ich bekomme ja nur 1024 Bytes "Päckchen", teile hier die Länge in "Päckchen" ein. :)
Das ist Unsinn.
Du stellst eine HTTP-Anfrage und bekommst eine HTTP-Antwort, die das Bild enthalten könnte, aber nicht muss!
Ob das Bild drin ist - und wie groß es ist - steht in der HTTP-Antwort.
In dem Fall ist das Bild drin. Das ist nur ein Test-Programm, da ist alles gültig, habe alles mit telnet probiert.

====
Eine Frage zu den Char's:
Char ist mein größtes Problem, wenn ich hier offen und ehrlich sein darf.
Mochte es nie zu verwenden und werde es wie's aussieht auch nicht.

Komme aber hier mit der Funktion hier nicht weiter:

Code: Alles auswählen

int Socket::c_recv ( char& s ) const {
  char buf [ MAXRECV + 1 ];
  s = 0;
  memset ( buf, 0, MAXRECV + 1 );

  int status = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( status > 0 || status != -1 ) {
     memset(&s, *buf, strlen(buf)+1);
     return status;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}
Als Antwort erhalte ich nur eine Buchstabe (237 x "H").
Da klappt was mit memset glaube ich nicht.

Die Funktion, wo ich es aufrufe ist:

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");
    char* response = new char[1024];
    client.c_recv(*response);
    cout << strlen(response);
    delete [] response;
}
EDIT:
Problem gelöst.

Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Re: Datei runterladen

Beitrag von Kmitska » Sa Jul 07, 2012 10:47 am

Also Leute, habe es jetzt so gemacht, wie Ihr es mir gesagt habt...

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");

    char* response = new char[1024];
    client.c_recv(*response);

    ofstream nFile("image.PNG", std::ios::out | std::ios::binary | std::ios::ate );

    for(short i=0; i<=(30308/1024); i++){
        memset(response, 0, strlen(response)+1);
        client.c_recv(*response);
        nFile.write(response, strlen(response));
    }
    nFile.write("\0", 1);
    delete [] response;
}
Und zum Testen schreibe ich die Informationen gleich in die Datei rein.
Da ich nicht weiß, wie man das zusammen schmidet ohne strcat().

Doch mein Problem wurde dadurch nicht behoben.

Und ich lese die Größe ja vom Header ab, also bei Content-Length steht 30308.
Und so rufe ich die Funktion auf:

Code: Alles auswählen

downloadFile( "www.airtrake.square7.ch", "http://airtrake.square7.ch/webseite/community.PNG" );

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Datei runterladen

Beitrag von Xin » Sa Jul 07, 2012 11:42 am

Kmitska hat geschrieben:Also Leute, habe es jetzt so gemacht, wie Ihr es mir gesagt habt...
Glaube ich nicht, aber es klingt erstmal richtig ;-D

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");

    char* response = new char[1024];
    client.c_recv(*response);

    ofstream nFile("image.PNG", std::ios::out | std::ios::binary | std::ios::ate );

    for(short i=0; i<=(30308/1024); i++){
        memset(response, 0, strlen(response)+1);
        client.c_recv(*response);
        nFile.write(response, strlen(response));
    }
    nFile.write("\0", 1);
    delete [] response;
}
[/quote]
Wenn ich mir den Code so angucke, wird Deine Datei kleiner als 30208 sein.

Offenbar hast Du immernoch nicht verstanden, dass es einen Unterschied zwischen Binärsten und Strings gibt. Binärdaten können 0 enthalten, Strangs nicht. strlen() prüft, wann die 0 kommt, die einen String beendet. Nochmal: In Binärdaten sind häufig 0len drin.

Also muss Dein c_recv auch eine Länge zurückliefen, wieviele Daten überhaupt gelesen wurden.
Hier haben String-Funktionen nirgendwo irgendwas zu suchen und am Ende der Binären Datei gehört auch kein zusätzliches Nullbyte.

Die Socket-Klasse - wo hast Du die geklaut? Bevor Du Klassen von anderen benutzt, solltest Du idealerweise verstehen, was Du tust. Da Du den Unterschied zwischen Strangs und Binärdaten noch nicht kennst, glaube ich nicht, dass Du verstehest, was in der Socket-Klasse vor sich geht.

Du versuchst Dinge ans Laufen zu bekommen, die Du noch nicht verstehst. Das wird sehr viele Fehler verursachen. Wer einen Berg besteigen will, sollte nicht mit dem Gipfel anfangen, der erste Schritt beginnt am Grund des Berges. Ohne gutes Fundament wirst Du laufend abstürzen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Re: Datei runterladen

Beitrag von Kmitska » Sa Jul 07, 2012 12:42 pm

Okay... jetzt verstehe ich das langsam... (endlich :-) )

Habe jetzt alle string-Funktionen raus geschnitten:

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");

    int len = 0;
    char* response = new char[1024];
    client.c_recv(*response);

    ofstream nFile("image.png", std::ios::out | std::ios::binary | std::ios::ate );

    for(short i=0; i<=(30308/1024)+1; i++){
        memset(response, 0, 1024);
        len = client.c_recv(*response);
        nFile.write(response, len);
    }
    delete [] response;
}
und

Code: Alles auswählen

int Socket::c_recv ( char& s ) const {
  char buf [ MAXRECV + 1 ];
  s = 0;
  memset ( buf, 0, MAXRECV + 1 );

  size_t len = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( len > 0 ) {
     memcpy(&s, &buf, len);
     return len;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}
Jetzt sieht doch alles schön nett aus, oder? :-)
Die Länge wird übermittelt und ersetzt + es werden nur Binärfunktionen verwendet.
Was könnte noch falsch sein?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Datei runterladen

Beitrag von Xin » Sa Jul 07, 2012 1:30 pm

Kmitska hat geschrieben:Okay... jetzt verstehe ich das langsam... (endlich :-) )

Habe jetzt alle string-Funktionen raus geschnitten:

Code: Alles auswählen

    for(short i=0; i<=(30308/1024)+1; i++){
        memset(response, 0, 1024);
        len = client.c_recv(*response);
        nFile.write(response, len);
    }
    delete [] response;
}
Das könnte erstmal funktionieren...
Kmitska hat geschrieben:

Code: Alles auswählen

int Socket::c_recv ( char& s ) const {
Das hier ist semantisch falsch. Du möchtest nicht ein char referenzieren, sondern Du übergibst den Zeiger auf den Beginn eines Arrays.
Praktisch passiert hier das gleiche, aber der Code suggeriert, dass Du mit einem char arbeiten möchtest und das willst Du nicht. Arbeite mit char *!
Kmitska hat geschrieben: Jetzt sieht doch alles schön nett aus, oder? :-) ... Was könnte noch falsch sein?
a) Funktioniert es, b) Ich habe weder den vollständigen Code, noch bin ich Betatester - woher soll ich wissen, was noch falsch ist. :-)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Re: Datei runterladen

Beitrag von Kmitska » Sa Jul 07, 2012 3:28 pm

Alsoooo... so sieht das ganze im Moment aus:

Code: Alles auswählen

int Socket::c_recv ( char* s ) const {
  char buf [ MAXRECV ];
  memset ( buf, 0, MAXRECV );

  size_t len = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( len > 0 ) {
     memcpy( s, buf, len);
     return len;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}
und die Funktion:

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");

    int len = 0;
    char* response = new char[1024];
    client.c_recv(response);

    ofstream nFile("image.png", std::ios::out | std::ios::binary | std::ios::ate );

    for(short i=0; i<=(30308/1024)+1; i++){
        memset(response, 0, 1024);
        len = client.c_recv(response);
        nFile.write(response, len );
    }
    delete [] response;
}
Beim Aufrufen:

Code: Alles auswählen

downloadFile( "www.airtrake.square7.ch", "http://airtrake.square7.ch/webseite/community.PNG" );
Und trotz Allem, es funktioniert nicht.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Datei runterladen

Beitrag von Xin » Sa Jul 07, 2012 5:34 pm

Kmitska hat geschrieben:Alsoooo... so sieht das ganze im Moment aus:
...
Und trotz Allem, es funktioniert nicht.
a) http://www.proggen.org/doku.php?id=faq:frageformulieren
xin hat geschrieben:b) Ich habe weder den vollständigen Code, noch bin ich Betatester - woher soll ich wissen, was noch falsch ist.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Datei runterladen

Beitrag von cloidnerux » Sa Jul 07, 2012 6:37 pm

Und trotz Allem, es funktioniert nicht.
Wie Xin schon sagte, präzisiere dich.
Was Funktioniert nicht uns wieso ist dem deiner Meinung nach so?
Sehr wichtig ist hierbei auch, das du dir ganz genau anschaust, welche Daten du rein bekommst, welche Daten du heraus bekommst und wo sie sich in wie fern unterscheiden.
Oftmals ist es so, dass man ganz andere Daten als erwartet bekommt. Prüft man das nicht, dann wird da auch niemals was gescheites bei heraus kommen.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Re: Datei runterladen

Beitrag von Kmitska » Sa Jul 07, 2012 10:42 pm

Also Leute... man erkennt jetzt zumindest das Bild von außen aus und wenn mans öffnet kommt ein weißes Bild.

Da sind nach meiner Meinung nach irgendwelche Bytes verschluckt wurden.
Hier ist nochmal der aktuelle Code:

Code: Alles auswählen

void downloadFile( string server, string file )
{
    Socket client;
    client.create();
    client.connect(server, 80);
    client.send("GET " +  file + " HTTP/1.1\r\n");
    client.send("Host: " + server + "\r\n\r\n");

    int len = 0;
    char* response = new char[1024];
    len = client.c_recv(response);

    ofstream nFile("image.png", std::ios::out | std::ios::binary | std::ios::ate );

    int endLines = 0;
    for(int n=0; n<=len; n++){
        if(response[n] == '\n'){
            endLines++;
            if(endLines == 9){
                endLines = n;
                break;
            }
        }
    }
    char* tmp = new char[len-endLines];
    memcpy(tmp, response+endLines+1, len-endLines );
    nFile.write(tmp, len-endLines );
    delete [] tmp;
    for(short i=0; i<=(30308/1024); i++){
        memset(response, 0, 1024);
        len = client.c_recv(response);
        nFile.write(response, len );
    }
    delete [] response;
}

Code: Alles auswählen

int Socket::c_recv ( char* s ) const {
  char buf [ MAXRECV +1 ];
  memset ( buf, 0, MAXRECV+1 );

  size_t len = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( len > 0 ) {
     memcpy( s, buf, len);
     return len;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}
Ich glaube eher, dass bei c_recv etwas nicht stimmt.
Hoffentlich könnt Ihr mir hier helfen. :)

Antworten