我正在尝试使我的客户端套接字无阻塞。但不成功。我不确定如何解决它。 我正在尝试构建一个简单的聊天框,我正在使用tkinter进行GUI。
要注意的主要部分是我在代码中分段的 while循环
我的客户代码是:
.
.
.
class GroupFrame(Frame):
def __init__(self, master):
super().__init__(master)
global memList
global rootHome
self.master.geometry("400x500")
self.master.resizable(width=FALSE, height=FALSE)
self.master.title("PowerPuff Chat Girls")
#TextArea
self.ChatLog = Text(self, bd=0, bg="light grey", height="13", width="55", font="Arial")
self.ChatLog.insert(END, 'Welcome to the PowerPuff Chat, ' + username + '\n', 'INIT')
self.ChatLog.config(state=DISABLED)
self.ChatLog.tag_config('INIT', foreground='red', justify=CENTER)
self.ChatLog.tag_config('BLUE', foreground='blue', justify=LEFT)
self.ChatLog.tag_config('BLK', foreground='black', justify=RIGHT)
#ScrollBar
self.scrollbar = Scrollbar(self, command = self.ChatLog.yview, cursor="heart")
self.ChatLog['yscrollcommand'] = self.scrollbar.set
#EntryBox
self.EntryBox = Text(self, bg="white", width="29", height="5", font="Arial")
self.EntryBox.bind("<KeyRelease-Return>", lambda event: sendData(self.EntryBox.get(1.0, END)))
#SendButton
self.SendButton = Button(self, font=30, text="Send", width="11", height=1,
bg="white", fg='navy blue', activebackground="#FACC2E", command=lambda: sendData(self.EntryBox.get(1.0, END)))
#Place them on Screen
self.scrollbar.place(x=380, y=6, height=386)
self.ChatLog.place(x=8, y=6, height=405, width=370)
self.EntryBox.place(x=128, y=425, height=60, width=248)
self.SendButton.place(x=6, y=425, height=60)
def sendData(param):
if param == '\n\n':
self.EntryBox.delete(1.0, END)
return
if len(param) > 1:
if '\n\n' in param:
# strip both the carriage return and appened with only one.
param = param.rstrip('\n')
param = param + '\n'
self.EntryBox.delete(1.0, END)
insertText(1, '>>' + param)
s.sendall(str.encode(param))
# data = s.recv(4500)
def inspectData(data):
if 'joined the chat **\n' in data.decode('utf-8'):
insertText(3, data.decode('utf-8'))
else:
insertText(2, '>>' + data.decode('utf-8'))
self.ChatLog.see(END) # this shows the END of the chatlog; auto scroll down
def insertText(num, param):
self.ChatLog.config(state=NORMAL)
if num == 1:
self.ChatLog.insert(END, param, 'BLK')
if num ==2 :
self.ChatLog.insert(END, param, 'BLUE')
if num ==3:
self.ChatLog.insert(END, param, 'INIT')
self.ChatLog.config(state=DISABLED)
*******************************************************
while True:
try:
data = s.recv(4096)
if(data):
inspectData(data)
except:
break
*******************************************************
page = Tk()
page.geometry("400x500")
page.resizable(width=FALSE, height=FALSE)
pf = HomeFrame(page)
page.mainloop()
使用我当前的代码,当我运行它时,客户端只是在当前位于 GroupFrame 框架时冻结。 我不确定为什么会这样。如果我没有明白我的问题请告诉我,这样我就可以提供一些有用的图像和部分代码。
答案 0 :(得分:1)
所呈现的代码存在一些不同的问题。主要问题是while
函数中的__init__
循环。这将使__init__
永远运行(假设套接字阻塞)。反过来,这将阻止Tk的主循环,从而阻止整个程序。
使用Tk时,必须意识到Tk拥有主循环。这意味着必须始终允许Tk运行,以使发布到其内部事件队列的事件出列。如果您的程序需要执行其他操作,例如,监听套接字,则必须在单独的线程中完成此操作,或者将其合并到Tk循环中。
不幸的是,没有通用的方法来使Tk循环的套接字输入部分。但是,我们可以做的是使用after
发布某个事件,以确保主循环在一定时间后调用预定义函数。这可用于创建解决方案,在某些时候可以轮询套接字,并检查是否有新数据要处理。
另一种方法是在单独的线程中运行套接字,将消息(通过同步的Queue
)发布到Tk线程。这可能是一个更通用的解决方案,但它仍然需要主循环轮询队列而不是套接字。
这一切都有点消化。我建议您尝试进一步减少您的示例,然后在较小的示例中询问是否存在仍然难以掌握的部分。
答案 1 :(得分:0)
我设法解决了我的问题。如果其他人有类似的问题轮询从Tkinter循环内的另一个套接字接收的数据。这就是我修复它的方法:
创建一个函数,轮询框架内的套接字,并在该框架内创建一个单独的线程来运行它。
代码:
def polling():
while True:
try:
polledData = s.recv(4096)
print(polledData.decode('utf-8'))
except:
pass #or you can print out the exception if you need to.
threading.Thread(target = polling, args=[]).start()