2014-02-20 138 views
1

制作聊天服务器的客户端部分。线程正常工作,就像接收数据一样,但是我得到一个属性错误,试图将数据从“receive_data”函数放入chatlog。我哪里错了?Python - 属性错误

from tkinter import * 
import socket 
import threading 
import time 

host = socket.gethostname() 
port = 8000 

s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

class Application(Frame): 
    def __init__(self, master=None): 
     #Create master frame 
     Frame.__init__(self,master) 
     self.grid() 
     self.master.title("Test 1") 
     self.conn=False #State of connection to server 


     #Configure main frame 
     for r in range (4): 
      self.master.rowconfigure(r, weight=1) 
     for c in range (2): 
      self.master.columnconfigure(c) 

     #Create sub frames 
     TopFrame=Frame(master, bg="red") 
     TopFrame.grid(row=0, column=0, rowspan=3) 
     BottomFrame=Frame(master, bg="blue") 
     BottomFrame.grid(row=4, column=0) 
     SideFrame=Frame(master, bg="green") 
     SideFrame.grid(column=1, row=0, rowspan=4) 

     #Create Chat log 
     self.chatlog=Text(TopFrame) 
     self.chatlog.pack(padx=5, pady=5) 

     #Create entry field 
     self.e1=StringVar() 
     self.e1=Entry(BottomFrame) 
     self.e1.pack(pady=5, padx=5) 

     #Create buttons 
     b1=Button(SideFrame, text="Connect", command=self.connect) 
     b1.grid(row=0, column=0, padx=5, pady=5) 
     b2=Button(SideFrame, text="Disconnect", command=self.disconnect) 
     b2.grid(row=1, column=0, padx=5, pady=5) 
     b3=Button(SideFrame, text="Send", command=self.sendmessage) 
     b3.grid(row=2, column=0, padx=5, pady=5) 

    def connect(self): #Connect to server 
     self.chatlog['state'] = NORMAL 
     self.chatlog.insert(END, ("===ATTEMPTING TO CONNECT TO SERVER\n")) 
     self.chatlog['state'] = DISABLED 
     self.chatlog.yview(END) 
     try: 
      s.connect((host,port)) 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===CONNECTED TO SERVER\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
      self.conn=True 
      print("Connected") #Connection successful 
      t1=RecvThreadClass() 
      t1.start() 

     except ConnectionRefusedError: #Can't find server 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===SERVER COULD NOT BE FOUND\n" + "===PLEASE MAKE SURE THE SERVER IS ON, AND YOU'RE CONNECTED TO THE NETWORK\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
     except: #Other errors 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===THERE'S AN ERROR WITH THE PROGRAM\n" + "===PLEASE TURN IT OFF AND ON AGAIN\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 

     # When attempting to connect a second time, produces OS error: an operation was attempted on something that is not a socket 

    def disconnect(self): 
     if self.conn: #Tests to see if client is connected 
      s.close() 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===DISCONNECTED FROM SERVER.\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 
      self.conn=False 
     else: #Prevents attempting to disconnect when already disconnected 
      self.chatlog['state'] = NORMAL 
      self.chatlog.insert(END, ("===YOU AREN'T CURRENTLY CONNECTED.\n")) 
      self.chatlog['state'] = DISABLED 
      self.chatlog.yview(END) 


    def sendmessage(self): 
     if self.conn: #Prevents sending if not connected 
      self.msg=self.e1.get() 
      if self.msg == "": #Empty message catcher 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===YOU CANNOT SEND AN EMPTY MESSAGE.\n")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 
      else: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ('You: ' + self.msg + '\n')) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 
       self.send_data(self.msg) #Sends message 
     else: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===YOU ARE NOT CONNECTED TO A SERVER. YOU CANNOT SEND A MESSAGE.\n")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 


    def send_data(self, message): 
     try: 
      s.send(message.encode('UTF-8')) 
     except: 
       self.chatlog['state'] = NORMAL 
       self.chatlog.insert(END, ("===THE PREVIOUS MESSAGE DIDN'T SEND. THIS IS POSSIBLY DUE TO A SERVER ERROR.\n===Disconnect and reconnect.")) 
       self.chatlog['state'] = DISABLED 
       self.chatlog.yview(END) 


class RecvThreadClass(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 

    def run(self): 
     receive_data() 


def receive_data(): 
    print("Preparing to receive") 
    while 1: 
     data=s.recv(1024) 
     print("Data received") 
     decoded_data=data.decode('UTF-8') 
     print(decoded_data) 
     Application.chatlog['state'] = NORMAL 
     Application.chatlog.insert(END, ('Server: ' + decoded_data + '\n')) 
     Application.chatlog['state'] = DISABLED 
     Application.chatlog.yview(END) 

root = Tk() 
app = Application(root) 
app.mainloop 
+2

什么是异常的(完整)回溯? –

+0

此代码可能无法可靠地工作 - 您不应该从非GUI线程调用GUI方法。 Tkinter的设计不是可以从多个线程调用的。 –

回答

1

您尝试在的类,而不是app实例访问chatlog。将所有Application引用app

def receive_data(): 
    print("Preparing to receive") 
    while 1: 
     data=s.recv(1024) 
     print("Data received") 
     decoded_data=data.decode('UTF-8') 
     print(decoded_data) 
     app.chatlog['state'] = NORMAL 
     app.chatlog.insert(END, ('Server: ' + decoded_data + '\n')) 
     app.chatlog['state'] = DISABLED 
     app.chatlog.yview(END) 

只有实例都有一个chatlog属性(在Application.__init__()创建)。

+0

我知道我会错过这样简单的事情。谢谢。 – QuarterGeekster