Ich moechte mit Sockets(!) einen Http-Request absetzen und die komplette Antwort erhalten. Da die Antwort ueber mehrere Pakete verteilt sein koennte, muss ich mehrfach empfangen. Das ist solange kein Problem solange mir der zustaendige Webserver einen Content-Laenge sendet. Viele Webserver tun dies leider nicht. Gibt es eine zuverlaessige Moeglichkeit herauszufinden wann eine Antwort zu Ende ist, außer einem Timeout?
Du musst Dich auf jeden Fall mit dem HTTP Protokoll befassen.
Beim kurzen Überfliegen des Codes erkenne ich nicht, dass Du
zuerst den Header erfasst und anschliessend die Body Daten.
Wichtig zu wissen ist, dass der Header mit "\r\n" getrennt wird...
tabellar hat geschrieben:Du musst Dich auf jeden Fall mit dem HTTP Protokoll befassen.
Beim kurzen Überfliegen des Codes erkenne ich nicht, dass Du
zuerst den Header erfasst und anschliessend die Body Daten.
Wichtig zu wissen ist, dass der Header mit "\r\n" getrennt wird...
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 7
Hello Tobi...
Tabellar
Jepp, das habe ich gemacht. Ich trenne header und Daten und versuche die Content-Length auszulesen. Das Problem ist, dass diese nicht immer gesendet wird vom Webserver
jens hat geschrieben:Es dürfte so ähnlich gehen, wie ein file-Objekt auslesen... Solange, bis keine Daten mehr kommen...
while 1:
data = conn.recv(1024)
if not data: break
...
Ja, Den Ansatz hatte ich auch, das Problem ist, dass sobald alle Daten da sind recv trotzdem weiterlaeuft und weiterhin versucht daten zu bekommen. Dies tut recv solange bis wirklich wieder was ueber die Leitung kommt. Man koennte das natuerlich ueber einen Timeout loesen aber das ist sehr unsauber, wie ich finde
tobias.hartwich hat geschrieben:Ja, Den Ansatz hatte ich auch, das Problem ist, dass sobald alle Daten da sind recv trotzdem weiterlaeuft und weiterhin versucht daten zu bekommen.
HTTP-Nachrichten können einen Rumpf beliebiger Länge enthalten, so daß ein Mechanismus definiert werden muß, um das Ende einer Nachricht zu bestimmmen. HTTP/1.0 stellt dafür den Content-Length Header zur Verfügung, der die Länge des Nachrichtenrumpfes enthält. Dazu muß aber offensichtlich die Länge der Entität bereits im voraus bekannt sein, was bei dynamisch generierten Entitäten nicht der Fall ist. Bisher mußten solche Entitäten vollständig generiert und gepuffert werden, um ihre Länge zu berechnen und konnten erst dann verschickt werden, wodurch die Antwortzeit (bei großen Antworten deutlich) anwächst. Bei HTTP/1.0 ist dies noch kein bedenkliches Problem gewesen, da der Content-Length Header nicht notwendig gewesen ist, das Ende der Nachricht ist ja durch das Schließen der Verbindung markiert worden. In HTTP/1.1 ist dies nicht mehr sinnvoll, daher ist eine bessere Möglichkeit entwickelt worden, die fragmentierte Transferkodierung (Chunked Transfer-Encoding):
Der Sender zerlegt die Nachricht in Fragmente beliebiger Länge, die mit ihrer Länge verschickt werden, wobei ein leeres Fragment das Ende der Nachricht bezeichnet. Der Sender markiert eine fragmentierte Nachricht durch den Header Transfer-Encoding: chunked.
Dadurch kann der Sender jeweils nur kleine Teile der Nachricht puffern, ohne daß merklich Komplexität oder Overhead hinzugefügt wird. Aufgrund der Einfachheit dieser Lösung müssen alle HTTP/1.1-Implementationen dieses Verfahren unterstützen.
Danke, deine Loesung funktioniert bei mir auch - Aber leider nicht fuer alle Seiten. Hab es jetzt noch einmal getestet mit quasi deiner Loesung aber bei mir versucht er am Ende weiterhin zu empfangen - genau da liegt das Problem
import socket, re
REQUEST = "GET / HTTP/1.1 \r\n Host: lesty.de\r\n\r\n"
class HTTPCON:
def __init__(self):
self.__meinsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__meinsocket.connect( ( "lesty.de", 80 ) )
self.__meinsocket.send(REQUEST)
chunk = ""
while 1:
data = self.__meinsocket.recv(1024)
if not data:
break
print data
chunk += data
print chunk
self.__meinsocket.close()
HTTPCON()
//EDIT: Hab es gerade nochmal mit HTTP 1.0 getestet. ich weiß nicht warum - aber damit funktioniert es?! //EDIT2: Hab rausgefunden, dass ein Vorteil von HTTP 1.1 ist, dass persistente Verbindungen aufgebaut werden. Die muss man natuerlich auch schließen - also Es klappt nun - Danke