套接字线程与PyGTK
我正在尝试写一个即时通讯程序,基本的界面已经差不多完成了,现在我在研究接收消息的部分。我有一个UI类和一个线程接收的Receive_Socket类。每当Receive_Socket类的socket接收到一条消息时,它会调用gobject.idle_add()来执行一个UI方法,以便把消息显示在聊天窗口里。在gobject.idle_add()这一行之后,我有一个while循环,这个循环会一直运行,直到消息确实显示在聊天窗口里(我希望消息在接收另一条消息之前就能显示出来,因为我了解到gobject.idle_add()并不能保证执行顺序,当然我希望消息是按顺序显示的 :))
我试着总结一下我的代码:
UI 类:
Class UI:
##### somewhere in the init #####
self.message_status = 0
def chat_window(self, contact, message=0):
Check if a chat window is opened for the contact, if not it opens one.
=> In reality this check if a gtk.Window containing a gtk.Notebook is opened,
=> if not it opens one
=> Then it creates a page for the contact in the notebook, containing a
=> gtk.Textview which displays messages
if message:
self.message_display(contact, message)
def message_display(self,a,b):
=> Display the message in the message in the contact's textview
self.message_status = 1
线程接收的Receive_Socket类:
Class Receive_Socket(threading.thread):
message = sock.recv(1024)
=> the sender name is written in the message
if message:
gobject.idle_add(myui.chat_window,sender, message)
while not myui.message_status:
time.sleep(0.1)
myui.message_status = 0
主代码:
if __name__ == "__main__":
myui = UI()
reception = Receive_Socket()
reception.start()
gtk.main()
我的问题:
1) 这种代码看起来高效吗?将一个线程接收类和我的UI类结合在一起是最好的做法吗?
2) 当消息显示出来时,socket可能已经接收到了两条或更多的消息,所以当它再次执行message = sock.recv(1024)时,多个消息会被合并到message变量里。我考虑在每条消息中包含消息长度,这样如果在1024字节中有超过一条消息,它会取出这条消息,把剩下的放到一个message_buffer变量中,然后在再次执行sock.recv(1024)之前,会检查message_buffer变量是否有内容,如果有,就把message_buffer的内容放到message变量中,而不是直接用sock.recv(1024)。有没有更简单或更好的解决方案呢?
提前谢谢你,
Nolhian
1 个回答
不,别用线程。相反,使用
glib.io_add_watch
,这样当套接字准备好读取时,gtk/glib会自动调用你的函数。这样你就不会让你的界面卡住,也不需要使用线程。同时,你也不需要用到idle_add
。如果你按照1的做法,就不会遇到这个问题,因为消息会按顺序到达,而且不会有多个线程同时运行导致数据混乱。