socket.recv() und tcp shutdown

Ich moechte Daten (Text Zeilen) via tcp von einem Server lesen. Leider erkennt socket.recv() nicht, dass der Server die Verbindung beendet hat und wartet so ewig. Mein Code: try: sock = socket.create_connection((server,port)) except socket.error as e: die("cannot connect to %s:%d - %s" % (server,port,e.strerror)) while True: line = '' while True: try: c = sock.recv(1) except socket.error as e: die("cannot read from %s:%d - %s" % (server,port,e.strerror)) if c == None: break if c == "\n": break line += c print(line) Ich haette erwartet, dass es am Ende zu der Fehlermeldung "cannot read" kommt oder dass c==None eintritt, aber sock.recv() blockiert und erkennt den tcp shutdown nicht. (Wie) kann man socket.recv() dazu bringen hier eine exception auszuloesen oder None zurueckzuliefern? Oder gibts ein anderes Modul, dass das besser/einfacher handhabt als socket? -- Ullrich Horlacher Server und Virtualisierung Rechenzentrum IZUS/TIK E-Mail: horlacher@tik.uni-stuttgart.de Universitaet Stuttgart Tel: ++49-711-68565868 Allmandring 30a Fax: ++49-711-682357 70550 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Florian Weimer <fw@deneb.enyo.de> wrote:
(Wie) kann man socket.recv() dazu bringen hier eine exception auszuloesen oder None zurueckzuliefern?
Gar nicht. Wenn das blockiert, heißt es, daß die TCP-Verbindung nicht sauber heruntergefahren wird.
In meinem Testfall hat der Server aber die TCP-Verbindung beendet.
Du mußt also einen Timeout einbauen.
Nein, das ist nicht akzeptabel. Ein request-response Protokoll waere damit viel zu instabil. Programme in anderen Programmiersprachen wie C oder Perl erkennen einen tcp shutdown, zB: curl http://fex.rus.uni-stuttgart.de/download/schwuppdiwupp.pl Geht das tatsaechlich nicht mit Python? Mein Python Testprogramm haengt sich hier auf. Mein Perl Testprogramm terminiert dagegen, weil es den tcp shutdown erkennt. -- Ullrich Horlacher Server und Virtualisierung Rechenzentrum IZUS/TIK E-Mail: horlacher@tik.uni-stuttgart.de Universitaet Stuttgart Tel: ++49-711-68565868 Allmandring 30a Fax: ++49-711-682357 70550 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Ich habs selber gefunden, die Loesung ist trivial :-) Ulli Horlacher <framstag@rus.uni-stuttgart.de> wrote:
Ich moechte Daten (Text Zeilen) via tcp von einem Server lesen. Leider erkennt socket.recv() nicht, dass der Server die Verbindung beendet hat und wartet so ewig.
Mein Code:
try: sock = socket.create_connection((server,port)) except socket.error as e: die("cannot connect to %s:%d - %s" % (server,port,e.strerror))
while True: line = '' while True: try: c = sock.recv(1) except socket.error as e: die("cannot read from %s:%d - %s" % (server,port,e.strerror)) if c == None: break if c == "\n": break line += c print(line)
Ich haette erwartet, dass es am Ende zu der Fehlermeldung "cannot read" kommt oder dass c==None eintritt, aber sock.recv() blockiert und erkennt den tcp shutdown nicht.
Knapp daneben :-) sock.recv(1) liefert bei tcp shutdown kein None zurueck, sondern ''! Es blockiert also gar nicht, wie ich faelschlicherweise angenommen hatte. Ich hatte also eine Endlosschleife produziert :-} (Ich haette auf den load achten sollen, dann waers mir aufgefallen) Leider steht das nicht in https://docs.python.org/2/library/socket.html So funktionierts nun: while True: line = '' while True: try: c = sock.recv(1) except socket.error as e: die("cannot read from %s:%d - %s" % (server,port,e.strerror)) if c == '' or c == "\n": break line += c print(line) if c == '': die("%s:%d has closed the connection" % (server,port)) -- Ullrich Horlacher Server und Virtualisierung Rechenzentrum IZUS/TIK E-Mail: horlacher@tik.uni-stuttgart.de Universitaet Stuttgart Tel: ++49-711-68565868 Allmandring 30a Fax: ++49-711-682357 70550 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/
participants (2)
-
Florian Weimer
-
Ulli Horlacher