blockierendes recv und accept

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

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. :)
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

@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?
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

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 ^^)
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

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.
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

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...
...meh...
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

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.
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

benutze unbedingt select oder poll, wenn du mit nonblocking sockets hantierst.
...meh...
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

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.
...meh...
blan
User
Beiträge: 23
Registriert: Donnerstag 4. Mai 2006, 17:30

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
Danic
User
Beiträge: 10
Registriert: Montag 8. Januar 2007, 20:56
Kontaktdaten:

Was denn für einen Fehler?
Antworten