Seite 1 von 1
blockierendes recv und accept
Verfasst: Donnerstag 4. Januar 2007, 20:11
von blan
hallo,
ich wollte fragen wie ihr das mit den blockierenen recv() und accept() löst. also ich hab für das accept() und für jeden client ein recv() -thread in einer schleife die solange läuft bis ein interrupted-flag gesetzt wird..
Code: Alles auswählen
while self.interrupted == False:
sock, addr = self.sock.accept()
Code: Alles auswählen
while self.interrupted == False:
data = self.sock.recv(100)
das problem ist jetzt natürlich, dass der thread mit dem interrupted-flag nicht gleich beendet wird sondern erst wenn nochmal eine verbindung (accept) oder daten (recv) eingehen. bis jetzt lös ich das ganze mit einem wohl eher radikalem
shutdown() und jeder menge try-abfragen weil da unter bestimmten umständen fehler auftreten... hat jemand von euch da eine bessere lösung?
mfg blan
Verfasst: Donnerstag 4. Januar 2007, 21:14
von Rebecca
Ich habe mal ein ganz primitives Chat-System so geschrieben:
Server:
http://paste.pocoo.org/show/556/
Client:
http://paste.pocoo.org/show/557/
Vielleicht findest du da ja Inspiration.

Verfasst: Donnerstag 4. Januar 2007, 22:06
von blan
genau so hab ich es auch gemacht. nur das problem ist, dass eben der thread nicht geschlossen wird. das passiert erst wenn data = None ist.
wir würdest du eine "exit"-funktion über den input implementieren - also dass bei der eingabe "exit" alles sauber beendet wird?
mfg blan
Verfasst: Donnerstag 4. Januar 2007, 22:16
von Sr4l
@Rebecca
Du beendest aber auch nicht vom Server aus einen Clienten?!?
@Blan
Ich weiß nicht das so macht, aber:
ich lasse eine Client Verbindung schließen in dem der Client einfach zumacht dann gibt es beim Server irgend ein Fehler 'Conection lost', 'refused' oder was auch immer.
***edit***
man könnte sagen wenn Client 'END' sendet sock.close() im server
oder soll der server bestimmen wann ein client rausfliegt?
Verfasst: Donnerstag 4. Januar 2007, 22:25
von blan
geht einfach darum, dass ich den server sauber runterfahren will. ansonsten hab ich immer tote threads die noch warten bis noch eine nachricht gesendet wird und dann erste beednet werden - das is aber natürlich nicht elegant
mfg blan
Verfasst: Donnerstag 4. Januar 2007, 22:55
von Sr4l
wenn der client brutal geschlossen wird einfach weg ge X oder kill oder sonst wie dann stirbt die verbindung auch sie endet dann in ienem kritischen fehler der dazuführt das der thread abstürztz (ausser du hast try except ^^)
Verfasst: Donnerstag 4. Januar 2007, 23:02
von blan
ja aber der client wird nicht brutal geschlossen sondern der server soll normal beendet werden und daran hindert mich eben das blockierende accept() und recv()
mfg blan
Verfasst: Freitag 5. Januar 2007, 02:46
von Sr4l
Dir würde nur helfen wenn du den Thread killst aber nicht von ihm selber sondern von aussen her aber ich musst auf der suche folgendes lesen:
http://aspn.activestate.com/ASPN/Cookbo ... cipe/65288
Code: Alles auswählen
This solution may be usefull for long running processes
like servers where you'd like to use threads but where you aren't
sure if all threads are ending. A pending problem in Python is still
the fact, that it isn't possible to kill a thread from outside of itself.
A receipe to solve this problem would be interesting ;-)
aber ich konnte auch folgendes finden:
http://mail.python.org/pipermail/python ... 60937.html
Code: Alles auswählen
This code module allows you to kill threads. The
class KThread is a drop-in replacement for
threading.Thread. It adds the kill() method, which
should stop most threads in their tracks.
es steht da ...which should stop most... das hört sich nicht besonders sicher (im bezug auf das es wirklich aufhört) an. Ich würds gerne noch testen ich gehe aber jetzt mal schlafen. morgen ist ja wieder ein harter Tag.
Verfasst: Freitag 5. Januar 2007, 06:57
von cracki
ideen:
* benutze non-blocking sockets und select/poll
* wenn ein thread sich beenden soll, mach das nicht von aussen sondern von innen: schick dem thread ueber ne steuerverbindung oder andere IPC (geh googeln) eine nachricht...
Verfasst: Freitag 5. Januar 2007, 14:56
von Sr4l
Damit du ihn von innen schließen kannst darf er nicht in einem blocking-socket stecken.
Ich habe hier mal meinen code.
Code: Alles auswählen
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((c['server'],c['port']))
sock.setblocking(0)
sock.listen(c['thread'])
#sock.setblocking(0)
while True:
channel, details = sock.accept()
channel.setblocking(0)
print "OPEN ", details
thread.start_new_thread(handle,(details,))
danke cracki non-blocking sockets sind die Antwort
aus Python Dokumentation Sockets 17.2.1
setblocking( flag)
Set blocking or non-blocking mode of the socket: if flag is 0, the socket is set to non-blocking, else to blocking mode. Initially all sockets are in blocking mode. In non-blocking mode, if a recv() call doesn't find any data, or if a send() call can't immediately dispose of the data, a error exception is raised; in blocking mode, the calls block until they can proceed. s.setblocking(0) is equivalent to s.settimeout(0); s.setblocking(1) is equivalent to s.settimeout(None).
Man kann also immer abfragen ob daten da sind wenn ja kann man sie verarbeiten wenn nein auch egal. Im nächsten schritt kann man prüfen ob man den socket schließen möchte wenn nein gehts wieder von vorne los.
Verfasst: Freitag 5. Januar 2007, 17:23
von cracki
benutze unbedingt select oder poll, wenn du mit nonblocking sockets hantierst.
Verfasst: Samstag 6. Januar 2007, 06:01
von blan
also ich habe mal nach beispiel codes geschaut aber finde nicht wirklich was zu "select" und "polling" - hat jemand von euch sowas zur hand?
mfg blan
Verfasst: Samstag 6. Januar 2007, 10:46
von cracki
Code: Alles auswählen
import select
import socket
i, o, e = select.select(ifd, ofd, ifd, select_timeout)
ifd, ofd, efd sind jeweils listen von sockets, die respektive geprueft werden auf:
es gibt was zu lesen
man kann schreiben
es gibt fehler
in i, o, e sind dann nur noch jeweils die sockets, fuer die jeweils die pruefung erfolgreich war.
select kehrt zurueck, so bald mindestens ein socket positiv getestet ist, oder das timeout verstrichen ist.
poll ist aehnlich. guck in den linux manpages nach.
Verfasst: Samstag 6. Januar 2007, 17:27
von blan
ich hab jetzt in der
library reference asyncore gefunden und finde es egtl auch richtig gut, nur weiss ich diesmal auchnocht wie ich aus dem ganzen ding wieder rauskomme
Code: Alles auswählen
import asyncore, socket
class http_client(asyncore.dispatcher):
def __init__(self, host, path):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect( (host, 80) )
self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
print self.recv(8192)
def writable(self):
return (len(self.buffer) > 0)
def handle_write(self):
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
c = http_client('www.python.org', '/')
asyncore.loop()
wenn ich beim "handle_connect"
self.close aufrufe bekomm ich einer fehler.. jemand eine idee?
mfg blan
Verfasst: Samstag 13. Januar 2007, 02:06
von Danic
Was denn für einen Fehler?