2010-12-15 4 views
3

Я пытаюсь написать программу обмена мгновенными сообщениями, базовый ui почти закончен, и я просматриваю принимающую часть сообщений. У меня есть UI-класс и потоковый класс Receive_Socket. Каждый раз, когда сокет класса Received_Socket получает сообщение, он вызывает gobject.idle_add() для вызова метода пользовательского интерфейса, чтобы отобразить сообщение в окне чата. После строки gobject.idle.add() у меня есть цикл while, цикл которого показывается на самом деле в окне чата (я хочу, чтобы сообщение отображалось перед получением другого сообщения, потому что я читал, что gobject.idle_add() не гарантирует порядок выполнения, и, конечно, я хочу сообщения, которые будут отображаться в порядке :))Socket Thread и 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) этот вид кода, кажется ли эффективным? Это (Имея многопоточный класс приема вместе с моим классом пользовательского интерфейса), лучший способ продолжить работу?

2) К моменту появления сообщения сокет может получать 2 или более сообщений, поэтому, когда сообщение message = sock.recv (1024) снова, в сообщении переменной будет объединено несколько сообщений. Я думал о включении длины сообщения в каждом сообщении, поэтому, если в 1024 байтах содержится более 1 сообщения, это займет сообщение, а остальные останутся в переменной message_buffer, и, прежде чем снова выполнить sock.recv (1024), он проверит, переменная message_buffer содержит что угодно, и если это так, поместите message_buffer в переменную сообщения вместо sock.recv (1024). Есть ли более легкое/лучшее решение для этого?

Спасибо заранее,

Nolhian

ответ

3
  1. No. Не используйте темы. Вместо этого используйте glib.io_add_watch, чтобы заставить gtk/glib сам вызвать вашу функцию, когда сокет готов к чтению. Таким образом, вы не будете замораживать свой gui и не будете нуждаться в потоках. Вам также не понадобится idle_add.

  2. Если вы делаете , у вас не будет этой проблемы, так как сообщения будут поступать по порядку, и не будет одновременных потоков, чтобы запутать данные.

+0

Спасибо, что работает очень хорошо! Просто вопрос о 2), как работает glib.io_add_watch? Например, я отправляю 3 сообщения в сокет, когда он получает первый, он вызывает обратный вызов, написанный в glib.io_add_watch, но при обработке обратного вызова другие 2 сообщения будут приниматься сокетом и поэтому, когда обратный вызов будет завершен (return True), он увидит, что сокет имеет данные и снова запускает обратный вызов, но на этот раз fd.recv (1024) будет содержать конкатенированные 2 сообщения, нет? – Nolhian 2010-12-15 23:20:49

Смежные вопросы