Chat Programm mit threading

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
PythonBytesMonty
User
Beiträge: 3
Registriert: Samstag 26. Mai 2012, 18:43

Hallo Pythonistas

Da ich neu hier bin, erstmal etwas zu mir, bzw. meiner Arbeitsumgebung:

-Ubuntu(Kernel 2.6.39.4)
-Programmiere unter IDLE (using Python-3.1)
-Habe python 2.6.5 und python 3.1.2 installiert (wenn ich was ausführe wird 2.6.5 benutzt)

Lerne mit:

-Galileo Openbook "Python das umfassende Handbuch"
Link zum Openbook: http://openbook.galileocomputing.de/python/
-O'Reillys Taschenbuch "Python kurz und gut" << Geschenk vom Bekannten

Bin sehr motiviert mich intensiv mit Python(nebst Linux[z.Z LPIC1]) zu beschäftigen,weil:

-Mich als Programmieranfänger C ziemlich frustriert hat...
-Mich ein "älterer" Bekannter (48 Jahre ,Fach-Informatiker) dazu bewegt hat
-Ich gerne meine (hoffentlich bald "guten") Scripts auch der breiten Masse
zur Verfügung stellen will (I <3 Open Source ;)
-Ich sehr gerne hier im Forum selbst Hilfe anbieten will
-Mir Python einfach (die genauen Gründe würden wohl die wenigsten
interessieren...) sehr gefällt

Falls jemand mehr (hoffe das war nicht zuviel...) Informationen braucht, ich werd sie gerne geben...

Im Openbook wird ein einfaches Chat Programm (Socket-Methode, tcp) vorgestellt (was nicht wirklich brauchbar ist...). Anschliessend wird dem Leser die "Herausforderung" gestellt, das Programm mit Threads zu etwas Brauchbarem (ich will auch mehrere Nachrichten nacheinander schreiben/empfangen können, (ob sich die Ausgabe/Eingabe kreuzen ist mir noch egal)) zu erweiteren, was ich gerade versuche (habe auch das Kapitel zum Modul threading gelesen).

Ich krieg das leider noch nicht so recht hin :( Habe erst das Client Programm erweitert. Ist wahrscheinlich ziemlicher Murks, es funktioniert aber teilweise (der Client emfängt nix, kann aber schreiben). Die Funktion zum beenden ("if message == "exit") wird folgendermassen quittiert:

traceback (most recent call last):
File "./test_thread.py", line 38, in <module>
answer = client_socket.recv(1024)
File "/usr/lib/python2.6/socket.py", line 165, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor

Habe das (Fehler bei der beenden Funktion) nur zur Vervollständigung gepostet, da es sich anscheinend um ein anderes Problem handelt (ist für mich z.Z. auch nicht so wichtig, Erklärungen würden trotzdem gern gesehen =)).

Der Server(unverändert), verhält sich wie erwartet (erst schreiben, dann empfangen usw...).


Hier nun die Codes:

Client:

Code: Alles auswählen

import socket
import threading

ip = raw_input("Enter IP: ")
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, 666))

class SendThread(threading.Thread):
    def __init__(self,message):
        threading.Thread.__init__(self)
        self.Message = message
        

class RecvThread(threading.Thread):
    def __init__(self,answer):
        threading.Thread.__init__(self)
        self.Answer = answer


my_threads = []

try:
    while True:
        message = raw_input("Message: ")
        client_socket.send(message)
        if message == "exit":
            break
        
        thread_send = SendThread(str(message))
        my_threads.append(thread_send)
        thread_send.start()

finally:
    client_socket.close()

try:
    while 1:
        answer = client_socket.recv(1024)
        print "[%s] tells you: %s" % (ip, answer)
        
    thread_recv = RecvThread(str(answer))
    my_threads.append(thread_recv)
    thread_recv.start()
    
finally:
    for t in my_threads:
        t.join()


Server:

Code: Alles auswählen

import socket


server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 666))

try:
    while True:
        commun, addr = server_socket.accept()
        while True:
            data = commun.recv(1024)
            if not data:
                commun.close()
                break
            print "[%s] %s " % (addr[0], data)
            message = raw_input("Enter your Message: ")
            commun.send(message)
finally:
    server_socket.close()


Ich hoffe habe alles richtig gemacht (ist ja mein allererster Forum-Post) und dass mir jemand die Richtung weisen kann (d.h. etwas zwischen "benutz Google" und dem fertigen Code!)

Hab mir mit diesem Post sehr Mühe gegeben nicht in die Kategorie "Ich will!!! Gebt mir!!!" zu gehören(will ja was lernen), deshalb wäre ich echt dankbar für brauchbare Antworten. Wie gesagt ich werde mich, sobald ich "etwas auf'm Kasten habe" auch bei der Community revanchieren!

MFG Lars alias PythonBytesMonty
BlackJack

@PythonBytesMonty: Das Openbook ist zumindest im OOP-Bereich nicht gut.

Zum Client: Deine Threads machen nichts. Wenn Du `start()` aufrufst, dann wird die `run()`-Methode in einem neuen Thread ausgeführt, nur hast Du gar keine `run()`-Methoden implementiert.

Es wäre so auch falsch aufgeteilt. Du hast im ersten Teil eine „Endlosschleife” die Nachrichten vom Benutzer entgegen nimmt und sie per Socket versendet. Das erstellen, starten, und sammeln von Thread-Objekten ist da total sinnfrei. Du willst nicht in den beiden Endlosschleifen unzählige Threads starten, sondern diese beiden Schleifen müssen in zwei verschiedenen Threads laufen, damit sie eben nicht nacheinander sondern nebenläufig ausgeführt werden. Dazu brauchst Du nur *einen* zusätzlichen Thread, denn den anderen hast Du ja schon automatisch weil das Programm ja auch in einem läuft.

Der Fehler ist auch leicht erklärbar: Wenn Du 'exit' eingibst wird die erste Schleife mit dem ``break`` verlassen, im ``finally``-Zweig wird das Socket-Objekt geschlossen, und in der zweiten Schleife wird dann versucht von einem geschlossenen Socket-Objekt Daten zu empfangen — das geht natürlich nicht.
PythonBytesMonty
User
Beiträge: 3
Registriert: Samstag 26. Mai 2012, 18:43

Hi BlackJack

Danke für die schnelle Antwort!
Hab mir schon gedacht dass da im Moment ziemlich viel verkehrt ist, konnte aber nach unzähligen Versuchen nicht mehr und brauchte Hilfe. Hab heute etliche Stunden damit verbracht, ohne befriedigendes Ergebniss... Ist für dich wohl lächerlich, aber jeder hat ja mal klein angefangen :) Versuche deine Tipps nun anzuwenden und werde mein Ergebniss posten.

Ach ja, welches Buch/Tutorial würdest du mir empfehlen? Möchte mich vor allem mit der Netzwerkprogrammierung beschäftigen. Kann auch was kosten...
OOP finde ich(wie ich das beurteilen kann) ziemlich wichtig/nützlich, deshalb sollte der Buchtip eher darin gut sein als Sockets etc.. genau zu erklären (dazu hab ich über Google einiges gefunden, ist mir aber oft noch zu kompliziert...)

Danke nochmals für die Hilfe und noch schöne (hoffentlich) freie Tage!
MFG PythonBytesMonty
BlackJack

@PythonBytesMonty: Das Tutorial in der Python-Dokumentation sollte man IMHO mal durchgearbeitet haben. Eventuell nach dem man etwas für Anfänger durch hat, falls das Tutorial in der Python-Dokumentation zu hoch ansetzt. „Learn Python The Hard Way” wird da gerne empfohlen. Kann man kostenlos als HTML lesen, oder als Buch oder E-Buch kaufen.

Speziell für Sockets gibt es in der Python Dokumentation das Socket Programming HOWTO. Da wirst Du zum Beispiel lernen, dass `recv()` und `send()` wie Du es benutzt zu einfach gedacht ist und die Programme im jetzigen Zustand auch ohne die Threads fehlerhaft wären.

Mit Socket-Programmierung und Threads hast Du Dir gleich zwei Themen ausgesucht, die auch erfahrene Programmierer herausfordern. Und es dehalb versuchen zu vermeiden, in dem höhere Schichten anstatt Bytes über Sockets direkt zu verschicken verwendet werden, und ereignisbasierte Rahmenwerke wie `twisted` oder `gevent` um die Threads los zu werden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Für Sockets gibt es natürlich noch "TCP/IP Illustrated" als Standardwerk für die Grundlagen. Ist aber nicht Python-spezifisch.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
PythonBytesMonty
User
Beiträge: 3
Registriert: Samstag 26. Mai 2012, 18:43

@Blackjack & Leonidas: Danke nochmals für die Antworten!

Fühle mich hier sehr gut aufgehoben. Bin echt noch ziemlich am Anfang und werd mir eure Tipps erstmal genau durchlesen und lernen. Hab mir mal das "umfassende Handbuch" für Linux gekauft und war (als Windows-Umsteiger) gut bedient. Dass der selbe Titel für Python, zumindest eben für Sockets oder OOP nicht so das Wahre sind hab ich nicht gewusst...
War halt von den wenigen Zeilen Code fürs Chat und den Threads sehr beeindruckt.

@ Leonidas: Besitze das Buch "TCP/IP - Studienausgabe" von Douglas E. Comer, welches mir auch als Standardwerk vorgeschlagen wurde. Es ist zwar für gewisse Zusammenhänge sehr interessant , aber für mich (jedenfalls um es auf die Programmierung anzuwenden) noch zu hoch ist :( Naja das wird schon... ;)

MFG und bis bald
PythonBytesMonty
Antworten