11 Stimmen

Implementierung eines Download-Managers, der die Wiederaufnahme unterstützt

Ich habe vor, einen kleinen Download-Manager in C++ zu schreiben, der die Wiederaufnahme (und mehrere Verbindungen pro Download) unterstützt.

Nach den Informationen, die ich bisher gesammelt habe, muss ich beim Senden der HTTP-Anfrage ein Header-Feld mit dem Schlüssel "Range" und dem Wert "bytes=startoff-endoff" hinzufügen. Dann gibt der Server eine HTTP-Antwort mit den Daten zwischen diesen Offsets zurück.

So grob, was ich im Sinn haben, ist die Datei auf die Anzahl der zulässigen Verbindungen pro Datei zu teilen und senden Sie eine http-Anfrage pro aufgeteilten Teil mit dem entsprechenden "Bereich". Wenn ich also eine 4 MB große Datei und 4 erlaubte Verbindungen habe, würde ich die Datei in 4 Teile aufteilen und 4 http-Anfragen senden, jede mit dem entsprechenden "Range"-Feld. Bei der Implementierung der Fortsetzungsfunktion würde man sich merken, welche Offsets bereits heruntergeladen wurden, und diese einfach nicht anfordern.

  • Ist dies der richtige Weg?
  • Was ist, wenn der Webserver die Wiederaufnahme nicht unterstützt? (ich vermute, er wird den "Bereich" ignorieren und einfach die gesamte Datei senden)
  • Sollte ich beim Senden der http-Anfragen im Bereich die gesamte aufgeteilte Größe angeben? Oder vielleicht fragen kleinere Stücke, sagen wir 1024k pro Anfrage?
  • Wenn ich die Daten lese, sollte ich sie sofort in die Datei schreiben oder eine Art von Pufferung vornehmen? Ich denke, es könnte verschwenderisch sein, kleine Stücke zu schreiben.
  • Sollte ich eine Memory-Mapped-Datei verwenden? Wenn ich mich richtig erinnere, wird sie eher für häufiges Lesen als für Schreiben empfohlen (ich könnte mich irren). Ist das vom Speicher her sinnvoll? Was ist, wenn ich mehrere Downloads gleichzeitig habe?
  • Wenn ich keine speicherabbildende Datei verwende, sollte ich die Datei für jede zulässige Verbindung öffnen? Oder soll ich, wenn ich in die Datei schreiben muss, einfach suchen? (Wenn ich eine Memory-Mapped-Datei verwenden würde, wäre dies wirklich einfach, da ich einfach mehrere Zeiger haben könnte).

Hinweis: Ich werde wahrscheinlich Qt verwenden, aber dies ist eine allgemeine Frage, so dass ich Code aus ihm herausgelassen.

7 Stimmen

Ich bin mir durchaus bewusst, dass es Dutzende von Download-Managern gibt, aber Sie verfehlen irgendwie den Punkt. Wenn jeder nach dieser Philosophie vorgehen würde, hätten wir 1 Programmiersprache, 1 Betriebssystem, 1 Browser, nun, Sie verstehen schon.

0 Stimmen

Beachten Sie, dass ich eine Frage gestellt habe, die Sie nicht beantwortet haben. Was war der Grund? Spaß? Fehlende Funktionen? Was?

2 Stimmen

Alle, schätze ich. ist das wirklich wichtig?

7voto

Bezüglich der Anfrage/Antwort:

für eine Range-d-Anfrage könnten Sie drei verschiedene Antworten erhalten:

206 Partial Content - Wiederaufnahme unterstützt und möglich; prüfen Sie den Content-Range-Header auf Größe/Bereich der Antwort
200 OK - Bytebereiche ("resuming") nicht unterstützt, ganze Ressource ("file") folgt
416 Requested Range Not Satisfiable - falscher Bereich (nach EOF usw.)

Content-Range sieht in der Regel so aus: Content-Range: bytes 21010-47000/47022 d.h. Bytes Anfang-Ende/Gesamt.

Prüfen Sie die HTTP-Spezifikation für Einzelheiten, insbesondere die Abschnitte 14.5, 14.16 und 14.35

4voto

Raj Punkte 6790

Ich bin kein C++-Experte, aber ich hatte einmal eine .net-Anwendung entwickelt, die ähnliche Funktionen benötigte (Download-Planung, Unterstützung für die Wiederaufnahme, Priorisierung von Downloads)

Ich habe die Komponente Microsoft BITS (Background Intelligent Transfer Service) verwendet, die in C entwickelt wurde. Windows Update verwendet ebenfalls BITS. Ich habe mich für diese Lösung entschieden, weil ich nicht glaube, dass ich als Programmierer gut genug bin, um selbst etwas auf diesem Niveau zu schreiben ;-)

Obwohl ich mir nicht sicher bin, ob Sie den Code von BITS bekommen können, denke ich, dass Sie einen Blick in die Dokumentation werfen sollten, die Ihnen helfen könnte zu verstehen, wie sie es implementiert haben, die Architektur, die Schnittstellen, etc.

Hier ist es - http://msdn.microsoft.com/en-us/library/aa362708(VS.85).aspx

0 Stimmen

BITS ist eine nette (und relativ unbekannte) Windows-Funktion; seien Sie jedoch darauf vorbereitet, auf etwas anderes zurückzugreifen, wenn es nicht verfügbar/deaktiviert ist.

0 Stimmen

BITS ist schön, aber wie in der Antwort nur verstehen, wie es entwickelt wird und nicht direkt verwenden, da BITS verwendet ungenutzte Netzwerk-Bandbreite dh, Bandbreite nicht von einem Benutzer-Prozess verwendet.

3voto

em70 Punkte 6028

Neben der Verfolgung der Offsets, die den Beginn Ihrer Segmente markieren, und der Länge der einzelnen Segmente (es sei denn, Sie möchten diese bei der Wiederaufnahme berechnen, was bedeuten würde, dass Sie die Offset-Liste sortieren und den Abstand zwischen zwei von ihnen berechnen müssten), sollten Sie den Accept-Ranges-Header der vom Server gesendeten HTTP-Antwort überprüfen, um sicherzustellen, dass er die Verwendung des Range-Headers unterstützt. Der beste Weg, den Bereich anzugeben, ist "Range: bytes=START_BYTE-END_BYTE", und der von Ihnen angeforderte Bereich umfasst sowohl START_BYTE als auch END_BYTE, besteht also aus (END_BYTE-START_BYTE)+1 Byte.

Von der Anforderung von Micro Chunks würde ich abraten, da Sie durch eine Firewall-Regel zur Blockierung von HTTP Flood auf eine schwarze Liste gesetzt werden könnten. Im Allgemeinen würde ich vorschlagen, dass Sie keine Chunks kleiner als 1 MB und nicht mehr als 10 Chunks erstellen. Je nachdem, wie Sie Ihren Download kontrollieren wollen, können Sie, wenn Sie die Kontrolle auf Socket-Ebene haben, in Betracht ziehen, nur einmal alle 32K zu schreiben, oder die Daten asynchron zu schreiben.

Zur MMF-Idee kann ich nichts sagen, aber wenn die heruntergeladene Datei sehr groß ist, ist das keine gute Idee, da Sie eine Menge RAM verbrauchen und das System eventuell sogar zum Swappen veranlassen, was eine no effizient.

Was die Handhabung der Chunks angeht, so könnten Sie einfach mehrere Dateien erstellen - eine pro Segment - und optional den Speicherplatz vorab zuweisen, indem Sie die Datei mit so vielen \x00 als die Größe des Chunks (eine Vorabzuweisung kann Ihnen beim Schreiben während des Downloads etwas Zeit sparen, macht den Start des Downloads aber langsamer), und schreiben Sie dann schließlich einfach alle Chunks nacheinander in die endgültige Datei.

Eine Sache, die Sie beachten sollten, ist, dass einige Server eine Höchstgrenze für gleichzeitige Verbindungen haben, die Sie nicht im Voraus erfahren. Sie sollten also darauf vorbereitet sein, mit http-Fehlern/Timeouts umzugehen und die Größe der Chunks zu ändern oder eine Warteschlange für die Chunks zu erstellen, falls Sie mehr Chunks als die maximale Anzahl von Verbindungen erstellt haben.

3voto

Ich kann nicht alle Ihre Fragen beantworten, aber hier ist meine Meinung zu zwei von ihnen.

Stückchengröße

Es gibt zwei Dinge, die Sie bei der Größe der Chunks beachten sollten:

  1. Je kleiner sie sind, desto mehr Overhead entsteht beim Senden der HTTP-Anfrage.
  2. Bei größeren Datenpaketen besteht die Gefahr, dass die gleichen Daten zweimal heruntergeladen werden, wenn ein Download fehlschlägt.

Ich empfehle Ihnen, mit kleineren Datenpaketen zu arbeiten. Sie müssen jedoch einige Tests durchführen, um herauszufinden, welche Größe für Ihren Zweck am besten geeignet ist.

Im Speicher vs. Dateien

Sie sollten die Datenpakete in den Speicherpuffer schreiben und dann, wenn dieser voll ist, auf die Festplatte schreiben. Wenn Sie große Dateien herunterladen, kann es für Ihre Benutzer problematisch sein, wenn ihnen der Arbeitsspeicher ausgeht. Wenn ich mich richtig erinnere, speichert der IIS Anfragen, die kleiner als 256kb sind, im Speicher, alles, was größer ist, wird auf die Festplatte geschrieben, Sie sollten vielleicht einen ähnlichen Ansatz in Betracht ziehen.

2voto

Das ist nicht wirklich eine Antwort auf die ursprüngliche Frage, aber eine andere Sache, die erwähnenswert ist, ist, dass ein resumierbarer Downloader auch das letzte Änderungsdatum einer Ressource überprüfen sollte, bevor er versucht, das nächste Stück von etwas zu holen, das sich möglicherweise geändert hat.

0 Stimmen

Wir müssen auch überprüfen, dass die heruntergeladenen Dateien nicht manipuliert wurden, z. B. durch eine Art Hashing.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X