2010-12-15 79 views
3

我试图写一个即时消息程序,基本的用户界面几乎完成,我正在寻找消息的接收部分。我有一个UI类和一个线程化的Receive_Socket类。每当Received_Socket类的套接字接收到消息时,它都会执行gobject.idle_add()来调用UI方法,以便将消息显示在聊天窗口中。在gobject.idle.add()行之后,我有一个while循环,它循环直到消息实际上显示在聊天窗口中(我希望在接收另一条消息之前显示消息,因为我读取了gobject.idle_add()不保证执行顺序,当然我想按顺序显示的消息:))套接字线程和PyGTK

我想总结一下我的代码:

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)当显示消息时,套接字可能已经收到2个或更多消息,所以当它再次执行message = sock.recv(1024)时,多条消息将被连接在变量消息中。我想在每条消息中包含消息长度,所以如果在1024字节中有多条消息,它将接收消息并将其余消息放入一个message_buffer变量中,并在再次执行sock.recv(1024)之前检查是否message_buffer变量包含任何内容,如果是,则将message_buffer放入消息变量中,而不是sock.recv(1024)。有没有更容易/更好的解决方案来做到这一点?

由于提前,

Nolhian

回答

3
  1. 号不要使用线程。相反,使用glib.io_add_watch可以让套接字准备好读取时,gtk/glib本身调用你的函数。这样你就不会冻结你的GUI并且不需要线程。你也不会需要idle_add

  2. 如果你做,你不会有这个问题,因为消息将按顺序到达,并且不会有并发线程混淆数据。

+0

谢谢它真的很好!只是关于2)的一个问题,glib.io_add_watch如何真正起作用?例如,我向套接字发送了3条消息,当它接收到第一条消息时,它会调用写在glib.io_add_watch中的回调函数,但在处理回调函数时,其他2条消息将被套接字接收,因此,当回调完成时返回True),它会看到套接字有数据并再次启动回调,但这次fd.recv(1024)将包含连接的2条消息,不是吗? – Nolhian 2010-12-15 23:20:49

+0

@Nolhian:当然,你的协议在消息之间肯定有某种分隔符。所以你必须自己拆分消息,并使用缓冲区来保留部分消息,直到消息的其余部分尚未到达。另一种选择是使用'twisted' http://twistedmatrix.com/这是一个网络框架。它的主循环与gtk主循环兼容。 – nosklo 2010-12-16 04:35:51

+0

@nosklo:可以使用'glib。io_add_watch'绑定的套接字等待侦听? – Hibou57 2014-02-13 06:11:40