[Python-de] Problem mit SocketServer

Eugen Ruppert nomail at nomail.de
Mo Mai 6 18:09:03 CEST 2013


Hallo Alexander,

> Socket-Objekte blockieren per default. Zitat:
[...snip...]
> SocketServer.recv() blockiert jedoch nicht. Folglich läuft die while 
> Schleife durch und meine CPU-Last steigt auf 25%.
> 
> Dieses non-blocking Verhalten ist auch nicht dokumentiert.
> Anscheinend ging der Autor davon aus dass man nur Requests im Stile
> von HTTP absetzt :/

Was aus der Dokumentation nicht direkt ersichtlich ist: ein recv Aufruf
liefert einen leeren String, wenn die Gegenseite nicht mehr da ist:
http://docs.python.org/2/howto/sockets.html

Da recv(X) dann sofort zurückkehrt, ist das Verhalten durchaus mit
non-blocking vergleichbar. Also solltest Du zumindest ein:
if not self.data: break
einbauen.

Grundsätzlich würde ich aber davon abraten, recv(BUFF_SIZE) aufzurufen,
da man dann z.B zusätzlich prüfen muss, wie viele Daten ein recv()
überhaupt liefert. Es klappt zwar sehr oft (besonders im lokalen
Netzwerk ;) ), dass ein recv den ganzen Datenblock einließt, verlassen
darf man sich darauf nicht - es kann genauso 1 Byte sein.


Hier hilft StreamRequestHandler weiter oder ein makefile(socket).

import SocketServer
class MyTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        while True:
            self.data = self.rfile.readline().strip()
            if not self.data:
                break
            print self.data
            self.wfile.write(self.data.upper())

server = SocketServer.TCPServer(("localhost",2000), MyTCPHandler)
server.serve_forever()

Gut, dieses Beispiel schließt die Verbindung auch bei leeren
Zeilen (wobei dieses Verhalten gar nicht so unerwünscht sein könnte),
man könnte allerdings auch "read(MAX)" verwenden (dieses liest dann
entweder X Zechen oder bis zum EOF).


Eugen







Mehr Informationen über die Mailingliste python-de