TCP-Socket: recv im Hintergrund laufen lassen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
Kolazomai
User
Beiträge: 33
Registriert: Donnerstag 16. Februar 2006, 15:05
Kontaktdaten:

Hi,

Ich hab eine Frage:

Ist es möglich, bei einem ganz normalen TCP-Socket, der mit socket gemacht wurde, das .recv immer im Hintergrund laufen zu lassen? Es sollte aber immer noch möglich sein, etwas zu senden.

Die Socket-Instanz liegt ( leider ) in einer Klasse, sodass es wohl mit threading nicht geht ?

Danke für alle Antworten.

Mfg,

Kolazomai
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Kolazomai hat geschrieben:Die Socket-Instanz liegt ( leider ) in einer Klasse, sodass es wohl mit threading nicht geht ?
Was hat das damit zu tun?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Ist es möglich, bei einem ganz normalen TCP-Socket, der mit socket gemacht wurde, das .recv immer im Hintergrund laufen zu lassen? Es sollte aber immer noch möglich sein, etwas zu senden.
Nein. Ist es nicht. Genauso kann .send() blockieren (wenn er im blockierenden Modus ist, was der Standard ist, und es sieht nicht danach aus dass Du einen select-Reaktor gebaut hättest), und ich weiß nicht inwiefern es ein socket mag wenn gleichzeitig .recv() und .send() auf ihn aufgerufen werden, aber da würd ich mal davon ausgehen dass das unproblematisch ist.
--- Heiko.
Benutzeravatar
Kolazomai
User
Beiträge: 33
Registriert: Donnerstag 16. Februar 2006, 15:05
Kontaktdaten:

Ok,

erstmal danke für die Antworten.

Also ich muss praktisch in der Klasse threading.Thread erstellen, dort "run", das empfängt, definieren und wenn ich dann was senden will, stopp ich "run" einfach, sende was und starte "run" wieder ?

Mfg,

Kolazomai
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Wie wärs wenn Du ein bissel mehr Code postest, oder einfach mal erklärst was Du machen willst? Weil im Endeffekt kann ich nur sagen, dass das was Du jetzt eben gepostet hast in der Form definitiv nicht (so) geht. Aber wie gesagt, wenn wir ein bisschen mehr Überblick über das Problem haben kann man auch besser Hilfestellung geben.
--- Heiko.
Benutzeravatar
Kolazomai
User
Beiträge: 33
Registriert: Donnerstag 16. Februar 2006, 15:05
Kontaktdaten:

Hoi,

ich habs jetzt mit Threading gemacht. Anscheinend macht es ihm nix aus, gleichzeitig zu empfangen und zu senden.

Naja, dann poste ich hier mal meinen Source. Der ist aber noch sehr verbuggt und fast noch nichts ist verlinkt. Das Programm nennt sich YaPyI, ist ein IRC-Client, und hat Ähnlichkeiten mit YaST, so oft wie es atm crasht :P

@Leonidas: Hab doch Tkinter genommen,weils für meine Bedürfnisse reicht und es in dem "Python Ge-Packt" erklärt wird.

Und ja, es gibt schon irclibs, aber ich wollte keine hernehmen und alles von Neu auf coden. Ich machs ja eh alles nur aus Spass an der Freude und an der Herausforderung :) .

Es sind noch paar Kommentare drinnen, um Bugs zu fixxen. Die hab ich jetzt mal nicht rausgenommen.

Wenn die Mods es für richtig halten, könnt ihr es ja in CodeSnippets reinwerfen.

Edit:// Code verbessert ... Jetzt geht es einigermassen.

Na, dann mal los:

Code: Alles auswählen

#!/usr/bin/python
#
# Coded by Kolazomai
# Email: verdin_hochzeit@web.de
# Published under BSD-License



# ============================
# == Yet Another Python Irc ==
# ============================


import socket
import threading
from time import sleep
from Tkinter import *
from tkMessageBox import showerror

Version = "YaPyI Version0.1"
Logfile = open(".logfile.txt","a")
receiving = True



# ============================
# Main Class
# ============================
class Main(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        pass
        # Start in here :>

    # ----------------------------------

    def send_string(self,*args):
        string = ""
        for wat in args:
            string += wat+" "
        print "Send(send_string):",string
        self.server_connect.send(string+"\n")

    # ----------------------------------

    def connect_to_server(self,server,port):
        self.server_connect = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.server_connect.connect((server,int(port)))

    # ----------------------------------

    def run(self):
        #gui.start()
        while receiving==True:
            data = self.server_connect.recv(1024)
            general_text.insert(END,data)
            general_text.see(END)
        

    # ----------------------------------

    def login(self,nickname,username,server,description):
        main.send_string("PASS secretpass")
        main.send_string("NICK "+str(nickname))
        main.send_string("USER "+str(username),
                                 "localhost",
                                 str(server),
                                 # names = Firstname Lastname
                                 ":"+description)
        
        # Now we'll wait for the PING-Command
        while 1:
            wait = self.server_connect.recv(100)
            if wait[0:4] == "PING":
                main.send_string("PONG"+wait[4:])
                break
            # awful

        # Login should be succesfully
        # We should start the Receiving-Thread
        main.start()

    # ----------------------------------
    # Commands
    # ----------------------------------

    def join_channel(self,channel,password=None):
        if password <> None:
            main.send_string("JOIN",channel,password)
        else:
            main.send_string("JOIN",channel)

    # ----------------------------------

    def quit_(self,msg=None):
        try:
            if msg <> None:
                main.send_string("QUIT :"+msg,"[YaPyI]")
            else:
                main.send_string("QUIT")
            self.server_connect.close()
        except:
            pass
        receiving = False

    # -----------------------------------

    def leave_channel(self,channel):
        main.send_string("PART",channel)

    # -----------------------------------

    def topic(self,channel,new_topic=None):
        if new_topic <> None:
            # Change Topic
            main.send_string("TOPIC",channel,":"+new_topic,
                                     "[YaPyI]")
        else:
            # Receive the Topic
            main.send_string("TOPIC",channel)

    # -----------------------------------

    def get_names(self,channel):
        # Shows all users being in the channel
        main.send_string("NAMES",channel)

    # -----------------------------------

    def list_channels(self):
        # Lists all available Channels
        main.send_string("LIST")

    # -----------------------------------

    def invite(self,guy,channel):
        main.send_string("INVITE",guy,channel)

    # -----------------------------------

    def kick(self,channel,guy,comment=None):
        if comment <> None:
            main.send_string("KICK",
                                     channel,
                                     guy,
                                     ":"+comment+"[YaPyI]")
        else:
            main.send_string("KICK",
                                     channel,
                                     guy)

    # -----------------------------------

    def server_version(self,server=None):
        if server <> None:
            main.send_string("VERSION",server)
        else:
            main.send_string("VERSION")

    # -----------------------------------

    def stats(self,query,server=None):
        # query:
        # c :::
        # returns a list of servers which the
        # server may connect to or allow connections from
        # h :::
        # returns a list of servers which are
        # either forced to be treated as leaves or allowed to act as hubs
        # i :::
        # returns a list of hosts which the
        # server allows a client to connect from
        # k :::
        # returns a list of banned username/hostname
        # combinations for that server
        # l :::
        # returns a list of the server's connections,
        # showing how long each connection has been
        # established and the traffic over that connection in
        # bytes and messages for each direction
        # m :::
        # returns a list of commands supported
        # by the server and the usage count for each
        # if the usage count is non zero
        # o :::
        # returns a list of hosts from which
        # normal clients may become operators
        # y :::
        # show Y (Class) lines from server's configuration file
        # u :::
        # returns a string showing how long the server has been up
        if server <> None:
            main.send_string("STATS",query,server)
        else:
            main.send_string("STATS",query)

    # -----------------------------------

    def private_msg(self,receiver,text):
        main.send_string("PRIVMSG",receiver,":"+text)

    # -----------------------------------

    def channel_msg(self,channel,text):
        if text.split(" ") >= 2:
            # text is with a space letter
            main.send_string("PRIVMSG",channel,":"+text)
        else:
            # text is without a space letter => We don't need ":"
            main.send_string("PRIVMSG",channel,text)

    # -----------------------------------

    def who(self,name,operater=False):
        if operator == False:
            main.send_string("WHO",name)
        else:
            main.send_string("WHO",name,"o")

    # -----------------------------------

    def whois(self,guy,server=None):
        if server <> None:
            main.send_string("WHOIS",server,guy)
        else:
            main.send_string("WHOIS",guy)

    # -----------------------------------

    def whowas(self,guy,count=-1,server=None):
        if server <> None:
            main.send_string("WHOWAS",
                                     guy,
                                     str(count),
                                     server)
        else:
            main.send_string("WHOWAS",
                                     guy,
                                     str(count))

    # -----------------------------------

    def operator(self,user,password):
        # Become operator
        main.send_string("OPER",
                                 user,
                                 password)

    # -----------------------------------

    def away(self,message):
        # Set away message
        main.send_string("AWAY",
                                 ":"+message,
                                 "[YaPyI]")

    # -----------------------------------

    def change_nick(self,nick):
        main.send_string("NICK",nick)

    # -----------------------------------

    def execute_cmd(self,cmd):
        # This allows the proffesionell user
        # to execute commands himself
        a = cmd.split(" ")
        b = a[0].upper()
        a.remove(a[0])
        to_send = b+" "
        for x in a:
            to_send += " "+x
        print "Send:",to_send
        main.send_string(to_send)


# ==================================
# GUI - Graphical User Interface
# ==================================
class Gui(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    # -----------------------------------

    def run(self):
        while 1:
            root.update()
            general_text.see(END)
            sleep(10)
    
    # -----------------------------------

    def start_gui(self):
        root.grab_set()
        root.focus_set()
        root.mainloop()

    # -----------------------------------

    def menu_bar(self,master):
        self.menubar = Menu(master)
        
        # 1.) File -Menu
        self.filemenu = Menu(self.menubar,tearoff=0)
        self.filemenu.add_command(label="Connect",command=gui.connect_gui)
        self.filemenu.add_separator()
        
        # 1.1) Special Exit
        def destroy_all():
            main.quit_()
            master.destroy()
        
        self.filemenu.add_command(label="Exit",command=destroy_all)

        # 2.) Edit -Menu
        self.editmenu = Menu(self.menubar,tearoff=0)
        self.editmenu.add_command(label="Options",command=gui.options_gui)

        # 3.) Help -Menu
        self.helpmenu = Menu(self.menubar,tearoff=0)
        self.helpmenu.add_command(label="About",command=gui.about_gui)
        self.helpmenu.add_separator()
        self.helpmenu.add_command(label="Help",command=gui.help_gui)

        # Add the Menus
        self.menubar.add_cascade(label="File",menu=self.filemenu)
        self.menubar.add_cascade(label="Edit",menu=self.editmenu)
        self.menubar.add_cascade(label="Help",menu=self.helpmenu)

        # Add it to the root
        master.config(menu=self.menubar)

    # -----------------------------------

    def create_slave(self,master,title,geometry):
        slave = Toplevel(master)
        slave.title(title)
        slave.geometry(geometry)
        return slave

    # -----------------------------------

    def connect_gui(self):
        connect_window = gui.create_slave(root,"Connect [YaPyI]",
                                               "200x300+500+375")
        
        # 1.) Widgets

        # 1.1) Labels
        self.label_python = Label(connect_window,
                                  text="YaPyIrc-Client V0.1")
        label_server = Label(connect_window,text="Server:")
        label_port = Label(connect_window,text="Port:")
        label_username = Label(connect_window,text="Username:")
        label_nickname = Label(connect_window,text="Nickname:")
        label_description = Label(connect_window,
                                  text="Description:")

        # 1.2) Entries
        entry_server = Entry(connect_window)
        entry_port = Entry(connect_window)
        entry_username = Entry(connect_window)
        entry_nickname = Entry(connect_window)
        entry_description = Entry(connect_window)

        # 1.3) Buttons

        # 1.3.1) What the Ok-Button does ...
        def what_button_ok_does():
            # Fetch infos
            server = entry_server.get()
            port = entry_port.get()

            username = entry_username.get()
            nickname = entry_nickname.get()
            description = entry_description.get()

            # Connect
            try:
                main.connect_to_server(server,port)
                try:
                    main.login(nickname,username,server,description)
                    print "I'm here Oo"
                    # Now I'm logined
                    
                    # I will destroy the Connect-Window
                    connect_window.destroy()
                    
                    # And show the new chat :-)
                    gui.server_window(server,port,username)

                except:
                    showerror(title="ERROR!",
                              message="Failed to login\n"+
                              "Server: "+server+"\n"
                              "Port: "+port+" !")
                    connect_window.destroy()
            except:
                # Show Error Box
                showerror(title="ERROR!",
                          message="Couldn't connect to\n"+
                          "Server: "+server+"\n"
                          "Port: "+port+" !")
                connect_window.destroy()


        # 1.3.2) Create the Buttons
        button_ok = Button(connect_window,text="  OK  ",
                           command=what_button_ok_does)
        button_cancel = Button(connect_window,text="Cancel",
                               command=connect_window.destroy)

        # Place them
        sta_x1 = 5
        sta_x2 = 70
        self.label_python.place(x=50,y=1)
        label_server.place(x=sta_x1,y=25)
        entry_server.place(x=sta_x2,y=25)
        label_port.place(x=sta_x1,y=75)
        entry_port.place(x=sta_x2,y=75)
        label_username.place(x=sta_x1,y=125)
        entry_username.place(x=sta_x2,y=125)
        label_nickname.place(x=sta_x1,y=175)
        entry_nickname.place(x=sta_x2,y=175)
        label_description.place(x=sta_x1,y=225)
        entry_description.place(x=sta_x2,y=225)
        button_ok.place(x=50,y=260)
        button_cancel.place(x=120,y=260)

        # Set Focus
        connect_window.grab_set()
        connect_window.focus_set()
        connect_window.wait_window()

    # -----------------------------------

    def options_gui(self):
        self.options_window = gui.create_slave(root,"Options [YaPyI]",
                                               "200x150+500+375")
        self.options_window.grab_set()
        self.options_window.focus_set()
        self.options_window.wait_window()

    # -----------------------------------

    def about_gui(self):
        self.about_window = gui.create_slave(root,"About [YaPyI]",
                                               "200x150+500+375")
        self.about_window.grab_set()
        self.about_window.focus_set()
        self.about_window.wait_window()

    # -----------------------------------

    def help_gui(self):
        self.help_window = gui.create_slave(root,"Help [YaPyI]",
                                               "200x150+500+375")
        self.help_window.grab_set()
        self.help_window.focus_set()
        self.help_window.wait_window()

    # -----------------------------------

    def show_usernames(self,names,master):
        self.listbox = Listbox(master, selectmode=SINGLE,width=20)
        for name in names:
            self.listbox.insert(END,name)
        # Place it :o
        self.listbox.pack()

    # -----------------------------------

    def server_window(self,server,port,username):
        # 1.) Create a new window
        a_new_window = gui.create_slave(root,
                                        server+":"+port+" [YaPyI]",
                                        "500x300+500+375")

        # 2.) Define Button-Action
        def send_button():
            what_to_send = entry_cmd.get()
            print what_to_send
            
            if what_to_send[0] == "/":
                # Send it as Command
                main.execute_cmd(what_to_send[1:])
            elif what_to_send == "":
                # If you don't send anything
                pass
            else:
                main.private_msg("#raid-rush",what_to_send)
            # Add it to the text-field
            text.insert(END,username+": "+what_to_send+"\n")

            # Clear entry
            entry_cmd.delete(0,len(what_to_send))
        
        # 3.) Widgets
        text = Text(a_new_window,background="white",height=20)
        entry_cmd = Entry(a_new_window)
        button_send = Button(a_new_window,text="Send",
                             command=send_button)

        # 4.) Pack 'em
        text.pack(fill = BOTH,
                  expand = YES)
        entry_cmd.pack(side = LEFT,
                       fill = BOTH,
                       expand = YES)
        button_send.pack(side = LEFT,
                         expand = NO)

        sleep(3)
        print "slept"
            
        


# ================================
# Start
# ================================

root = Tk()
root.title("YaPyI V0.1")
root.geometry("600x300+500+375")
general_text = Text(root,background="black",foreground="white")
general_text.pack(fill=BOTH,expand=YES)

gui = Gui()
main = Main()

gui.menu_bar(root)
gui.start_gui()
main.quit_()
Antworten