Datei runterladen

Schnelle objektorientierte, kompilierende Programmiersprache.
Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Datei runterladen

Beitrag von Kmitska » So Jul 01, 2012 2:48 pm

Hallo Leute,

ich möchte gerne paar Dateien von einem Server runterladen.
Als Beispiel habe ich mir dieses Bild hier ausgesucht:

Bild
Quelle: http://www.linux-mag.com/s/i/topics/tux.jpg

Das Problem ist: Ich habe keine Ahnung wie das geht, im Internet verstehe ich das ganze nicht.

Und wenn möglich:
Wie kann ich die Datei anzeigeigen lassen, ohne ihn zu speichern?

Hoffentlich könnt Ihr mir helfen/Tipps geben.

Grüße,
Kmitska

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

Re: Datei runterladen

Beitrag von cloidnerux » So Jul 01, 2012 6:49 pm

Das Problem ist: Ich habe keine Ahnung wie das geht, im Internet verstehe ich das ganze nicht.
Du brauchst entweder was wie "curl" oder du rufst Programme wie "wget" im Hintergrund auf.
Wie kann ich die Datei anzeigeigen lassen, ohne ihn zu speichern?
Gar nicht. Du brauchst die Daten irgendwie lokal auf deinem Rechner, also entweder speicherst du die Daten in deinem RAM oder auf der Festplatte, ohne geht nicht.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Fisherman
Beiträge: 84
Registriert: Mi Jun 06, 2012 4:53 am
Wohnort: 127.0.0.1

Re: Datei runterladen

Beitrag von Fisherman » So Jul 01, 2012 8:28 pm

Hallo Leute,
ich möchte gerne paar Dateien von einem Server runterladen.
Als Beispiel habe ich mir dieses Bild hier ausgesucht:
Da du dies in C/C++ gepostet hast, gehe ich mal davon aus das du es auch in dieser Sprache(n) umsetzen möchtest :
Da mit "Server" nicht das gewünschte Protokoll erläutert wurde, hier mal eine Anleitung um einen Webserver anzusprechen (http). Grundlagen der Netzwerkprogrammierung bei Beej's Network Guide.
Ich habe keine Ahnung wie das geht, im Internet verstehe ich das ganze nicht.
Ein Tip wäre dich mit dem OSI Modell vertraut zu machen. Danach mit den gewünschten Protokollen HTTP,FTP etc ...

Viel Spaß ;)

PS: Hab noch etwas gefunden - Quellcode anschauen
There is no place like 127.0.0.1

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

Re: Datei runterladen

Beitrag von Kmitska » So Jul 01, 2012 9:20 pm

cloidnerux hat geschrieben:
Das Problem ist: Ich habe keine Ahnung wie das geht, im Internet verstehe ich das ganze nicht.
Du brauchst entweder was wie "curl" oder du rufst Programme wie "wget" im Hintergrund auf.
Wie kann ich die Datei anzeigeigen lassen, ohne ihn zu speichern?
Gar nicht. Du brauchst die Daten irgendwie lokal auf deinem Rechner, also entweder speicherst du die Daten in deinem RAM oder auf der Festplatte, ohne geht nicht.
Ja, ich meinte RAM. (Mein Fehler)
Und "wget", geht das auch unter Windows?

Aber das mit RAM wäre mir eigentlich lieber, da ich das Bild nur anzeigen lasse.
EDIT: Wie kann ich "wget" selber schreiben?

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

Re: Datei runterladen

Beitrag von cloidnerux » So Jul 01, 2012 9:27 pm

Ja, ich meinte RAM. (Mein Fehler)
Und "wget", geht das auch unter Windows?

Aber das mit RAM wäre mir eigentlich lieber, da ich das Bild nur anzeigen lasse.
EDIT: Wie kann ich "wget" selber schreiben?
Soo, hier ist der Punkt, wo man dir sagen muss: Informiere dich oder lass es sein.
Das Internet und HTTP sind nicht furchtbar kompliziert, aber zu Kompliziert um es dir hier in einem Thread Detailgenau zu erklären. Es gibt genug Quellen, die auch von Fisherman schon aufgeführt wurden, die hinreichend genau beschreiben, was du suchst.

Auch habe ich dir curl, bzw libcurl schon ans herzgelegt, das implementiert ca das, was du haben willst. Ansonsten gibt es für Windows auch noch 1000 und ein Weg an Daten zu kommen, entweder über ActiVeX und ner IE instanz, über Windows Boardmittel oder über nem Socket, was du auch immer willst.
Aber das ganze ist kein 5 Minuten Projekt, wo du ein paar Zeilen Code zurecht tippen kannst und ich habe auch keine Lust dir die Grundlagen zu erklären.

Also, bitte lese dir die entsprechenden Quellen durch, oder lass es sein.

MfG cloidnerux.
Redundanz macht wiederholen unnötig.
quod erat expectandum

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 » Mo Jul 02, 2012 4:46 pm

Kmitska hat geschrieben:EDIT: Wie kann ich "wget" selber schreiben?
Du schreibst doch einen Crawler... Du kannst Websites runterladen? Dann kannst Du auch andere Daten runterladen - das Protokoll ändert sich nicht.

Aber Du musst es halt mal gründlich lesen. :-)
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 » Mi Jul 04, 2012 10:25 pm

Xin hat geschrieben:
Kmitska hat geschrieben:EDIT: Wie kann ich "wget" selber schreiben?
Du schreibst doch einen Crawler... Du kannst Websites runterladen? Dann kannst Du auch andere Daten runterladen - das Protokoll ändert sich nicht.

Aber Du musst es halt mal gründlich lesen. :-)
Danke Dir. :)

Also habe jetzt einiges raus bekommen, doch beim "Abfangen" habe ich Probleme.
In Header wird die Länge mitgeteilt:

Code: Alles auswählen

Content-Lenght: 30308
Um das Bild abzufangen habe ich dies ausprobiert:

Code: Alles auswählen

int main()
{
    Socket sock;
    sock.create();
    sock.connect("airtrake.square7.ch", 80);
    sock.send("GET http://airtrake.square7.ch/webseite/community.PNG HTTP/1.1\r\n");
    sock.send("Host: airtrake.square7.ch\r\n");
    sock.send("\n");

    string recv,img;
    sock.recv(recv);

    for(int n=0; n<=(30308/1024); n++){
        sock.recv(recv);
        img += recv;
    }
    ofstream file("image.png");
    file << img;
    return 1;
}
Doch beim Abspeichern kommt eine fehlerhafte Datei raus.
Wo mache ich falsch?

Und die Socket Klasse aus "C++ von A bis Z":
Header:

Code: Alles auswählen

#ifndef SOCKET_H_
#define SOCKET_H_
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>

using namespace std;

// Max. Anzahl Verbindungen
const int MAXCONNECTIONS = 5;
// Max. Anzahl an Daten die aufeinmal empfangen werden
const int MAXRECV = 1024;

// Die Klasse Socket
class Socket {
   private:
   // Socketnummer (Socket-Deskriptor)           
   int m_sock; 
   // Struktur sockaddr_in
   sockaddr_in m_addr;
   
   public:
   // Konstruktor
   Socket();
   // virtueller Destruktor
   virtual ~Socket();

   // Socket erstellen - TCP
   bool create();
   // Socket erstellen - UDP
   bool UDP_create();
   bool bind( const int port );
   bool listen() const;
   bool accept( Socket& ) const;
   bool connect ( const string host, const int port );
   // Datenübertragung - TCP
   bool send ( const string ) const;
   int recv ( string& ) const;
   // Datenübertragung - UDP
   bool UDP_send( const string, const string,
                  const int port ) const;
   int UDP_recv( string& ) const;
   // Socket schließen
   bool close() const;
   // WSAcleanup()
   void cleanup() const;
   bool is_valid() const { return m_sock != -1; }
   // für select()
   int get_m_sock() const { return m_sock; }
   void set_m_sock( int nr ) { m_sock = nr; }  
   
};

// Exception-Klasse
class SockExcept {
   private:
   string except;
   
   public:
   SockExcept( string s ) : except( s ) {};
   ~SockExcept() {};
   string get_SockExcept() { return except; }
};

#endif
Cpp:

Code: Alles auswählen

// socket.cpp
#include <cstdlib>
#include <iostream>
#include <cstring>
#include "socket.h"
using namespace std;

Socket::Socket() : m_sock(0) { }

Socket::~Socket() {
   if ( is_valid() )
      ::close( m_sock );
}

bool Socket::create() {
   m_sock = ::socket(AF_INET,SOCK_STREAM,0);
   if (m_sock < 0) {
      throw SockExcept("Fehler beim Anlegen eines Socket");
   }
   int y=1;
   setsockopt( m_sock, SOL_SOCKET,
               SO_REUSEADDR, &y, sizeof(int));
   return true;
}

bool Socket::UDP_create() {
   m_sock = ::socket(AF_INET,SOCK_DGRAM,0);
   if (m_sock < 0) {
      throw SockExcept("Fehler beim Anlegen eines Socket");
   }
   return true;
}

bool Socket::bind( const int port ) {
   if ( ! is_valid() ) {
      return false;
   }
   m_addr.sin_family = AF_INET;
   m_addr.sin_addr.s_addr = INADDR_ANY;
   m_addr.sin_port = htons ( port );

   int bind_return = ::bind ( m_sock,
      ( struct sockaddr * ) &m_addr, sizeof ( m_addr ) );
   if ( bind_return == -1 ) {
      return false;
   }
   return true;
}

bool Socket::listen() const {
   if ( ! is_valid() ) {
      return false;
   }
   int listen_return = ::listen ( m_sock, MAXCONNECTIONS );
   if ( listen_return == -1 ) {
      return false;
   }
  return true;
}

bool Socket::accept ( Socket& new_socket ) const {
   int addr_length = sizeof ( m_addr );
   new_socket.m_sock = ::accept( m_sock,
      ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );
   if ( new_socket.m_sock <= 0 )
      return false;
   else
      return true;
}

bool Socket::connect( const string host, const int port ) {
   if ( ! is_valid() )
      return false;
   struct hostent *host_info;
   unsigned long addr;
   memset( &m_addr, 0, sizeof (m_addr));
   if ((addr = inet_addr( host.c_str() )) != INADDR_NONE) {
       memcpy( (char *)&m_addr.sin_addr,
               &addr, sizeof(addr));
   }
   else {
       host_info = gethostbyname( host.c_str() );
       if (NULL == host_info) {
          throw SockExcept("Unbekannter Server");
       }
       memcpy( (char *)&m_addr.sin_addr, host_info->h_addr,
                host_info->h_length);
   }
   m_addr.sin_family = AF_INET;
   m_addr.sin_port = htons( port );

   int status = ::connect ( m_sock,
      ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

  if ( status == 0 )
    return true;
  else
    return false;
}

bool Socket::send( const string s ) const {
   int status = ::send ( m_sock, s.c_str(), s.size(),  0 );
   if ( status == -1 ) {
      return false;
   }
   else {
      return true;
   }
}

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

  int status = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( status > 0 || status != -1 ) {
     s = buf;
     return status;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}

bool Socket::UDP_send( const string addr, const string s, const int port ) const {
   struct sockaddr_in addr_sento;
   struct hostent *h;
   int rc;

   h = gethostbyname(addr.c_str());
   if (h == NULL) {
      throw SockExcept("Unbekannter Host?");
   }
   addr_sento.sin_family = h->h_addrtype;
   memcpy ( (char *) &addr_sento.sin_addr.s_addr,
            h->h_addr_list[0], h->h_length);
   addr_sento.sin_port = htons (port);
   rc = sendto( m_sock, s.c_str(), s.size(), 0,
                 (struct sockaddr *) &addr_sento,
                  sizeof (addr_sento));
   if (rc == -1) {
      throw SockExcept(
         "Konnte Daten nicht senden - sendto()");

   }
   return true;
}

int Socket::UDP_recv( string& s ) const {
   struct sockaddr_in addr_recvfrom;
   int len, n;
   char buf [ MAXRECV + 1 ];
   s = "";
   memset ( buf, 0, MAXRECV + 1 );
   len = sizeof (addr_recvfrom);
   n = recvfrom ( m_sock, buf, MAXRECV, 0,
                  (struct sockaddr *) &addr_recvfrom,
                  ( socklen_t * )&len );
   if (n == -1){
      throw SockExcept("Fehler bei recvfrom()");
      return 0;
   }
   else {
      s = buf;
      return n;
   }
}

void Socket::cleanup() const { }

bool Socket::close() const {
   ::close(m_sock);
   cleanup();
   return true;
}
Danke im Voraus.

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

Re: Datei runterladen

Beitrag von cloidnerux » Mi Jul 04, 2012 10:29 pm

Du hast wrsl durch die Verwendung von strings eine Null-Terminierte Datei und höchst wahrscheinlich noch Formatoptionen, die dir Automatisch deine Daten verwursten. Das ist natürlich nicht erwünscht, da du ja keinen text sondern Binäre Daten empfängst.
Folglich ist die Verwendung von einem unsigned char array angebracht, welches Dynamisch durch malloc oder ähnliches den erforderlichen speicher bereitstellt. Dadurch erst kannst du dir sicher sein, dass deine Daten korrekt übertragen werden.
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 » Do Jul 05, 2012 8:00 pm

Habe das nun so gemacht:

Code: Alles auswählen

int main()
{
    Socket sock;
    sock.create();
    sock.connect("airtrake.square7.ch", 80);
    sock.send("GET http://airtrake.square7.ch/webseite/community.PNG HTTP/1.1\r\n");
    sock.send("Host: airtrake.square7.ch\r\n");
    sock.send("\n");

    char* gesamt = new char[30308];
    char* antwort = new char [1024];
    sock.recv(*antwort);
    cout << antwort;

    for(int i=0; i<=(30308/1024); i++){
        sock.recv(*antwort);
        strcat(gesamt, antwort);
    }

    delete antwort;

    ofstream file("image.png");
    file << gesamt;

    delete gesamt;
    return 1;
}
Die Datei ist aber immernoch fehlerhaft, hier ist die umgeschriebene Funktion Socket::recv();:

Code: Alles auswählen

int Socket::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 ) {
     strcat(&s, buf);
     return status;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}
Was könnte da schief gehen? :/

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

Re: Datei runterladen

Beitrag von cloidnerux » Do Jul 05, 2012 8:13 pm

Was könnte da schief gehen? :/
Du nutzt immer noch String-Funktionen. strcat ist für Strings, also texte. Das Dingen addiert automatisch Null-Bytes.
Verwende Funktionen wie memcpy oder ähnliche. Denk immer daran, du willst binäre Daten verarbeiten und keine Texte.

Du könntest aber auch direkt deinen Buffer in die Datei schreiben.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten