HEAD-Alternative
Löffel
- https
0 josh0 Löffel0 josh0 Edgar Ehritt1 Thomas Luethi0 Edgar Ehritt0 josh
0 Engelein0 Edgar Ehritt0 ChrisB
Hi,
ich arbeite derzeit an einem Download-Programm und bin auf ein Problem gestoßen:
Da mein Downloader den Download über mehrere Slots startet, schicke ich zunächst ein HEAD-Request an den/die Server, um Informationen wie die Download-Größe zu erfahren.
Wird der Download jedoch bspw. über ein PHP-Skript ausgeliefert, das den speed regelt, dann hängt mein Programm jedes mal. Das liegt vermutlich daran, dass das Skript erst abgearbeitet wird und danach der Response geschickt wird. Und da das Skript mehrere sleeps beinhalten kann, um nicht zu viele Bytes pro Sekunde zu verschicken, kann es ziemlich lange dauern, bis das Skript fertig ist.
Eine Möglichkeit dies zu umgehen wäre, anstatt einem HEAD-Request einen normalen GET-Reuqest zu schicken und den Empfang zu canceln, nachdem ich alle Header empfangen habe.
Allerdings wäre dies nicht im Sinne des Erfinders. Hat evtl jemand noch eine andere Idee?
Gruss
Löffel
Hallo,
Das liegt vermutlich daran, dass das Skript erst abgearbeitet wird und danach der Response geschickt wird.
Sofern kein Output-Buffering verwendet wird, schickt PHP meines Wissens alle Ausgaben sofort ab (darum kommt es ja auch zur berühmten
Fehlermeldung der header()-Funktion).
Und da das Skript mehrere sleeps beinhalten kann, um nicht zu viele Bytes pro Sekunde zu verschicken, kann es ziemlich lange dauern, bis das Skript fertig ist.
Ich erkenne darin keinerlei Sinnhaftigkeit (wer zur Hölle verlangsamt seine Scripts absichtlich?!)...
Gruß
Sofern kein Output-Buffering verwendet wird, schickt PHP meines Wissens alle Ausgaben sofort ab (darum kommt es ja auch zur
berühmten
Fehlermeldung der header()-Funktion).Und da das Skript mehrere sleeps beinhalten kann, um nicht zu viele Bytes pro Sekunde zu verschicken, kann es ziemlich lange dauern, bis das Skript fertig ist.
Ich erkenne darin keinerlei Sinnhaftigkeit (wer zur Hölle verlangsamt seine Scripts absichtlich?!)...
Naja, stell dir vor, du bietest große Dateien zum Download an und musst den Speed drosseln, damit du deine Warteschlange genau kontrollieren kannst ;) Wie auch immer, Anwenungsbereiche gibt es immer und ich bin solchen Skripts schon öfter begegnet, wehalb ich das in meinem Programm beachten muss oder eher sollte ;)
Ich habe es gerade mal versucht. Habe ein PHP-Skript genommen, das den speed auf 500KB/s begrenzt und mir ein 6 MB File liefert.
Mein Downloader ist in Java geschrieben.
Schicke ich ein GET-Request, bekomme ich sofort den InputStream und kann schon die ersten Zeilen und somit die Header auslesen. Es wird also mittels flush() im Script erfolgreich der Inhalt an den Client übertragen.
Änder ich das GET in ein HEAD um, dann bekomme ich den InputStream nicht sofort, sondern erst etwa 12 Sekunden später. Da 500 KB * 12 Sek ungefähr 6 MB ist, liegt die Vermutung nahe, dass bei dem Head-Request eben nicht gleich der Content gesendet wird (ist ja der Sinn von HEAD) und damit erst das Skript abgearbeitet wird.
Ich habe auch testweise mal einen anderen DL-Manager versucht (Multiget, C++). Dieser schickt ebenfalls zunächst ein HEAD-Request. Wenn ein Timeout von 30 Sekunden erreicht ist, dann kennzeichnet er den DL als failed.
Ich habe jetzt ebenfalls erstmal ein ReadTimeout eingebaut.
Wenn allerdings noch jemand eine Idee hat, kann er sich gerne melden :)
Hallo,
Seltsam. Die PHP-Dokumentation behauptet nämlich etwas anderes (wenn auch an versteckter Stelle - suche nach REQUEST_METHOD). Könntest du bitte den Quellcode von deinem Testscript posten?
Funktioniert es denn mit Multiget?
Gruß
HALLO!
Naja, stell dir vor, du bietest große Dateien zum Download an und musst den Speed drosseln, damit du deine Warteschlange genau kontrollieren kannst ;) Wie auch immer, Anwenungsbereiche gibt es immer und ich bin solchen Skripts schon öfter begegnet, wehalb ich das in meinem Programm beachten muss oder eher sollte ;)
Au man...
Was andere falsch machen, macht ein braves Herdentier beratungsresistent auch nach. (Eine Frage zu Klassifizierung: Sagst Du "Muh" oder "Mäh"?)
Ich habe es gerade mal versucht. Habe ein PHP-Skript genommen, das den speed auf 500KB/s begrenzt und mir ein 6 MB File liefert.
Jemanden mit mehr Datendurchsatz wird von Dir grundlos ausgebremst. Jemand mit weniger Datendurchsatz hat davon keinerlei Vorteile. Die Maschine, auf der sich Dein Script befindet, muss einen Prozess mit recht großem Speicherverbrauch unnötig lange laufen lassen. Und wie Du selber fest gestellt hast, aber es offensichtlich mangels Wissen nicht besser interpretieren kannst, bremst Du download manager aus.
Summa summarum: Keine Vorteile - nur Nachteile.
Schicke ich ein GET-Request, bekomme ich sofort den InputStream und kann schon die ersten Zeilen und somit die Header auslesen. Es wird also mittels flush() im Script erfolgreich der Inhalt an den Client übertragen.
Änder ich das GET in ein HEAD um, dann bekomme ich den InputStream nicht sofort, sondern erst etwa 12 Sekunden später. Da 500 KB * 12 Sek ungefähr 6 MB ist, liegt die Vermutung nahe, dass bei dem Head-Request eben nicht gleich der Content gesendet wird (ist ja der Sinn von HEAD) und damit erst das Skript abgearbeitet wird.
Bei einer HEAD-Anfrage verfahren die meisten Server so, dass die gesamte Anfrage virtual abgearbeitet. Die Scriptausgaben werden also verworfen. Dieses könnte, wenn man eben keinen Blödsinn mit sleep() veranstaltet, binnen Sekundenbruchteilen geschehen.
Entschuldige bitte die anfänglich recht barschen Worte! Fehlgeleitet zu sein, ist nicht so sehr schlimm, wenn man sich müht zu hinterfragen und dadurch zu verbessern - bei Dir mangelt es aber an der Kondition. ^,-
Gruß aus Berlin!
eddi
Grundlage für Zitat #1065.
Hallo Eddi,
Im Eröffnungspost hat Löffel doch geschrieben:
ich arbeite derzeit an einem Download-Programm und bin auf ein Problem gestoßen: [...]
Das heisst, er will Dateien *herunterladen* von anderen Servern.
Und er muss damit rechnen, dass *dort* irgendwelche PHP-Skripts
zwischengeschaltet sind, die den Download (unnötig) verzögern,
was ein Problem für sein Download-Programm darstellt.
Ich sehe nirgends einen Hinweis darauf, dass Löffel selbst
solche Skripts mit sleep() in der Praxis einsetzt, wenn er
Dateien zum Download anbietet.
Deine Schelte war also IMHO unberechtigt.
Die inhaltliche Antwort und die Argumentation gegen sleep() ist
dagegen interessant und einleuchtend - danke!
Freundliche Grüsse, Thomas
Hallo,
Euch beiden dann nochmals:
Thomas, der OP wurde mehrfach (vgl. archiv, hier) auf die RFC 2616 verwiesen, zeigt sich aber lieber unverständig. (Ich muss Dir aber zugestehen, dass es so aussieht, als verstünde man sich hier in den Aussagen nicht. Das aber verfolgt einen Zweck. ;)
Hasi, wärst Du nur etwas beflissener beim Lesen der RFC gewesen, würdest Du Dein Programm darauf ausrichten, dass erst eine HEAD-Anfrage, dann eine GET-Anfrage mit bereits indirekt angedeuteten Range-Header, und dann eine 'normale' GET-Anfrage zu stellen wäre. Dass Du erst nach dem Post einen time out im Programm realisierst, kann ja keiner ahnen.
Gruß aus Berlin!
eddi
Hallo,
[...] dass erst eine HEAD-Anfrage, [...]
War nicht das Problem, dass irgendein ominöses Script eine halbe Ewigkeit für besagten HEAD-Request braucht?
(Verwirrter) Gruß
Hallo Josh,
[...] dass erst eine HEAD-Anfrage, [...]
War nicht das Problem, dass irgendein ominöses Script eine halbe Ewigkeit für besagten HEAD-Request braucht?
Ja. Zur Lösung gab es aber bereits den Ansatz eines time out. In wiefern man nur time out setzt oder gleich zu Java-Mitteln adäquat zu Systemaufrufen select() poll()
greift und nach Ablauf von (beispielsweise) zwei Sekunden eine weitere Anfrage per GET stellt, hätte vom OP einer Diskussion bedurft. Wie üblich kratzen Fragende allzu gern nur an der Oberfläche. ;(
Gruß aus Berlin!
eddi
Wird der Download jedoch bspw. über ein PHP-Skript ausgeliefert, das den speed regelt, dann hängt mein Programm jedes mal. Das liegt vermutlich daran, dass das Skript erst abgearbeitet wird und danach der Response geschickt wird.
Kann ich mir nicht so recht vorstellen. Es gibt einen PHP-Ausgabepuffer, aber der muss a) explizit eingeschaltet werden (wird selten gemacht) und b) puffert er üblicherweise nur wenige Kilobyte.
Eine Möglichkeit dies zu umgehen wäre, anstatt einem HEAD-Request einen normalen GET-Reuqest zu schicken
HEAD- und GET-Anfragen werden von Skripten so gut wie nie unterschieden - hakt es also bei HEAD, müsste es auch bei GET haken.
Du solltest dir Wireshark herunterladen, um den Netzwerkverkehr nachzuvollziehen.
Hallo,
Eine Möglichkeit dies zu umgehen wäre, anstatt einem HEAD-Request einen normalen GET-Reuqest zu schicken und den Empfang zu canceln, nachdem ich alle Header empfangen habe.
Allerdings wäre dies nicht im Sinne des Erfinders. Hat evtl jemand noch eine andere Idee?
sicher ist es nicht im Sinne des Erfinders ein GET-Anfrage zu starten und den Datenstrom nach den HTTP-Header nicht mehr entgegen zu nehmen. Nur stellt sich mir hier eine logische Frage: Wenn ein Script, das die Verarbeitung einer Anfrage durch sleep() verzögert, angerufen wird, warum sollte es einen Unterschied machen, ob die Anfragemethode GET oder HEAD ist; und überhaupt wer programmiert sowas mit sleep()?
Generell macht es schlichtweg keinen Sinn, upload-Scripte mittels sleep() zu verzögern. Der Webserver und PHP regeln das ganz ohne weiteres von allein. PHP hat schlichtweg auch keine Möglichkeit den Auslieferungsvortschritt generierter Daten zu überwachen, sodass es um so weniger sinn macht, mit sleep() zu verzögern.
Weiterhin kann PHP die Anfragemethode durch die Umgebungsvariable $_SERVER['REQUEST_METHOD']
bestimmen und darauf entsprechend reagieren. In diesem Zusammenhang ist von Engelchen ja schon das Stichwort Ausgabebuffer gefallen, mit dessen Hilfe man so nützliche Header wie Conten-Length oder auch Accept-Ranges (i. v. m. dessen Verarbeitung) erstellen kann und die Datenauslieferung gemäß http://tools.ietf.org/html/rfc2616#section-9.4@RFC unterbinden.
Gruß aus Berlin!
eddi
Hi,
Da mein Downloader den Download über mehrere Slots startet, schicke ich zunächst ein HEAD-Request an den/die Server, um Informationen wie die Download-Größe zu erfahren.
Wird der Download jedoch bspw. über ein PHP-Skript ausgeliefert, das den speed regelt, dann hängt mein Programm jedes mal. Das liegt vermutlich daran, dass das Skript erst abgearbeitet wird und danach der Response geschickt wird. Und da das Skript mehrere sleeps beinhalten kann, um nicht zu viele Bytes pro Sekunde zu verschicken, kann es ziemlich lange dauern, bis das Skript fertig ist.
Dann lass das Script halt was anderes machen (bspw. nur Dateigroesse auslesen und per entsprechendem Header zurueckgeben), wenn die anfordernde Methode HEAD war. $_SERVER liefert auch darueber Aufschluss.
MfG ChrisB