Logikfrage zu sockets und threads

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
Empi
User
Beiträge: 26
Registriert: Montag 29. März 2010, 14:05

Hallo zusammen.

Ich schreibe aktuell an einem kleinen Python Server.
Solange running = 1 wartet der Server auf eine Anfrage eines Clients (siehe Codeschnipsel).
Jetzt möchte ich, dass der Client ein Beendigungsflag an der Server schicken kann.
Hier habe ich aber ein Timingproblem, da die Serverfunktionen von einem Thread (LbServerThread)
abgehandelt wird.
Setze ich über den Thread running auf 0, so kann es vorkommen, dass das Setzen erst erfolgt,
nachdem die Serverklasse die Whileschleife bereits wieder passiert hat (zu diesem Zeitpunkt ist dass running noch 1) und schon wieder auf s.accept() wartet, was bedeutet, daß der Server erst beendet wird, sobald sich erneut ein Client am Server anmeldet.

Als alternative Lösung zum Flagsetzen habe ich in der Serverklasse eine statische Methode eingebaut, welche den Server mittels sys.exit(0) beenden soll. Wenn ich diese Methode aus dem Thread heraus jedoch aufrufe, dann passiert schlicht und einfach nichts.

Code: Alles auswählen

     while (running):
            con, addr = s.accept() #Warten bis ein Client eine neue Verbindung erstellen moechte
            server = LbServerThread(con, addr)
            server.start()
            ...
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Ich wuerde mir die Module asyncore und asynchat mal anschauen!

sys.exit raist eine SystemExit-Exception, die (falls du sie nicht aus versehen irgendwo abfaenst) nur den Thread selbst beendet. Das Programm beendet sich erst, wenn sich alle Threads beendet haben, es sei denn du nutzt daemonic Threads.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
Empi
User
Beiträge: 26
Registriert: Montag 29. März 2010, 14:05

Habe die Threads mal auf Daemons umgebogen, hat aber leider auch nicht den gewünschten
Erfolg gebracht. Als Workaround habe ich nach Setzen des Flags jetzt noch einen Dummy
Server Kontakt eingebaut. Ist zwar ziemlich gebastelt, funktioniert aber. :K
Sollte noch jemand eine bessere Lösung wissen ... :roll:
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Empi hat geschrieben:Habe die Threads mal auf Daemons umgebogen
Du musst dann das exit im Main-Thread aufrufen, denn dieser ist ja kein Daemon. Das Programm endet, wenn nur noch Daemonen-Threads laufen.

Threads sind nicht unbeding ideal fuer IO-lastige Anwendungen und haben ja auch so ihre Tricks. Mit select zu arbeiten ist da normalerweise die bessere Wahl, wie es eben asynchore/asynchat tun. Die Module nehmen dir einiges an Arbeit ab.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
Empi
User
Beiträge: 26
Registriert: Montag 29. März 2010, 14:05

Rebecca hat geschrieben:
Empi hat geschrieben:Habe die Threads mal auf Daemons umgebogen
Du musst dann das exit im Main-Thread aufrufen, denn dieser ist ja kein Daemon. Das Programm endet, wenn nur noch Daemonen-Threads laufen.

Threads sind nicht unbeding ideal fuer IO-lastige Anwendungen und haben ja auch so ihre Tricks. Mit select zu arbeiten ist da normalerweise die bessere Wahl, wie es eben asynchore/asynchat tun. Die Module nehmen dir einiges an Arbeit ab.
Ich werde mir asynchore/asynchat auf jeden Fall mal anschauen, jedoch muss ich ehrlich gestehen, daß ich ein zu 98% fertiges Programm nur extrem ungern umwerfen möchte. Rein aus Sicht der Performance ist das Programm absolut akzeptabel.

--> Main- Problem. Das Problem hier ist halt, dass .accept() bis zur nächsten Clientverbindung wartet - der Thread es aber (manchmal) nicht rechtzeitig schafft das Flag zu ändern - und mit Sachen wie sleep() werde ich erst gar nicht anfangen.
Du musst dann das exit im Main-Thread aufrufen
Wie gesagt, das habe ich mittels einer statischen Methode probiert, hat aber leider nicht funktioniert.
:twisted: Um mich mal schnell beliebt zu machen: In Java funktioniert sowas :twisted:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Empi hat geschrieben:Wie gesagt, das habe ich mittels einer statischen Methode probiert, hat aber leider nicht funktioniert.
:twisted: Um mich mal schnell beliebt zu machen: In Java funktioniert sowas :twisted:
Das einzige was du damit machst, ist zu zeigen, dass dein Verstaendnis hinkt.
Also: Code.

Wo wir schon bei Java sind: In Python braucht man keine Klammern bei while/if... D.h. `while running` reicht. Genauso kann man `running = True` nutzen und muss nicht auf Zahlen zurueckgreifen.
BlackJack

@Empi: Was wäre denn der Vorteil einer "statischen" Methode? Kann es sein, dass Du bei Java einfach nur Glück hast, dass das Flag dort immer rechtzeitig gesetzt wurde?
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

eine andere vielleicht nicht die beste Lösung, ist beim accept ein Timeout einzubauen, dann könntest du zum Beispiel jede Sekunde den Status prüfen.
http://docs.python.org/library/socket.h ... settimeout
Benutzeravatar
Empi
User
Beiträge: 26
Registriert: Montag 29. März 2010, 14:05

BlackJack hat geschrieben:@Empi: Was wäre denn der Vorteil einer "statischen" Methode? Kann es sein, dass Du bei Java einfach nur Glück hast, dass das Flag dort immer rechtzeitig gesetzt wurde?
Ob statisch oder nicht ist egal, Problem ist einfach nur der Zugriff vom Threadobjekt auf das Serverobjekt.
cofi hat geschrieben: Das einzige was du damit machst, ist zu zeigen, dass dein Verstaendnis hinkt.
Bitte nicht so ... Wenn ich die Lösung kennen würde (besser gesagt eine bessere wie meine aktuelle), dann würde ich hier nicht posten ;-)
cofi hat geschrieben: Wo wir schon bei Java sind: In Python braucht man keine Klammern bei while/if... D.h. `while running` reicht. Genauso kann man `running = True` nutzen und muss nicht auf Zahlen zurueckgreifen.
Das ist schon klar, ändert aber nichts an dem Problem.
Nebenbei noch erwähnt: http://www.peterbe.com/plog/bool-is-int

Gut. Um das ganze zu beenden: Habe das wie obig schon beschrieben gelöst.
Das mit dem Java bitte nicht ernst nehmen, war nur ein Scherz, deswegen auch die Smilies.

Vielen Dank für die vielen Hinweise und Lösungsansätze.
Zuletzt geändert von Empi am Mittwoch 28. Juli 2010, 12:27, insgesamt 1-mal geändert.
Benutzeravatar
Empi
User
Beiträge: 26
Registriert: Montag 29. März 2010, 14:05

BlackJack hat geschrieben:@Empi: Was wäre denn der Vorteil einer "statischen" Methode? Kann es sein, dass Du bei Java einfach nur Glück hast, dass das Flag dort immer rechtzeitig gesetzt wurde?
Noch ein kleiner Nachtrag:
Nein. Bei Java beendet system.exit(0) den gesamten Prozess und nicht "nur" den Thread.
Deswegen war statisch da möglich, wie oben bereits erfahren beendet sys.exit() bei Python den Thread, nicht den Prozess.
Antworten