我对Python很新,所以我很抱歉如果我的问题是业余的。线程化UDP侦听器函数
我想做一个简单的程序,允许用户看到正在广播的UDP消息。为了让程序不锁定,我当然需要创建一个单独的线程来监听广播。
在我试图执行线程之前,程序运行良好。它只是等待UDP消息,并在接收到一个消息时将它们显示在TextView
中。当然,这锁定了主线程。
这里是我的代码:(是的,我知道有我的代码一些无关紧要的问题,但请忽略它们例如,我从来没有关闭socket
以后我会解决这些问题。)
import socket
import select
import sys
import threading
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
except:
print("GTK not available!")
sys.exit(1)
class GUI:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("UDPListener.ui")
dic = {"on_mainWindow_destroy" : self.quit,
"on_listenButton_clicked" : self.startThread,
"on_stopListenButton_clicked" : self.stopListening}
self.builder.connect_signals(dic)
self.listenerThread = threading.Thread(target = self.listen)
def startThread(self, widget):
self.listenerThread.start()
def listen(self):
bufferSize = 1024
IPAddress = "0.0.0.0"
IPAddress: 0.0.0.0
portNumber = 50000
udpClient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
textView = self.builder.get_object("messagesReceivedEntry").get_buffer()
textView.text = textView.get_text(textView.get_start_iter(),textView.get_end_iter())
textView.set_text("Listening...")
try:
udpClient.bind((IPAddress, portNumber))
udpClient.setblocking(0)
except:
print "Cannot connect."
try:
while True:
result = select.select([udpClient],[],[])
message = result[0][0].recv(bufferSize)
print message
except:
print "Cannot receive message"
def quit(self, widget):
sys.exit(0)
def stopListening(self, widget):
pass
gui = GUI()
gtk.main()
代码将运行,一切运行正常,但它从不打印任何消息(我自己广播它们)。
UPDATE:
由于J.F.塞巴斯蒂安的回答,我改变了我的代码,包括以下内容:
import socket
import select
import sys
import threading
import gobject
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
except:
print("GTK not available!")
sys.exit(1)
gobject.threads_init()
class GUI:
def __init__(self, UDPClient):
self.udpClient = UDPClient
self.builder = gtk.Builder()
self.builder.add_from_file("TestUDPListenerREORG.ui")
dic = {"on_mainWindow_destroy" : self.quit,
"on_listenButton_clicked" : self.startThread,
"on_stopListenButton_clicked" : self.stopListening}
self.builder.connect_signals(dic)
self.textView = self.builder.get_object("messagesReceivedEntry").get_buffer()
self.textViewText = self.textView.get_text(self.textView.get_start_iter(),self.textView.get_end_iter())
self.listening = False
self.listenerThread = threading.Thread(target = self.listen)
def startThread(self, widget):
self.listenerThread.start()
pass
def listen(self):
try:
self.udpClient.connect()
except:
print "Cannot connect."
try:
while True:
result = select.select([self.udpClient.client],[],[])
message = result[0][0].recv(1024)
print message
gobject.idle_add(self.updateGUI, message)
except:
print "Cannot receive message"
def updateGUI(self, message):
print "updating..."
self.textView.set_text(self.textViewText + "\n" + message)
print message
def quit(self, widget):
self.udpClient.close()
sys.exit(0)
def stopListening(self, widget):
pass
class UDPClient:
def __init__(self, IPAddress, portNumber):
self.IPAddress = IPAddress
self.portNumber = portNumber
self.bufferSize = 1024
self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def connect(self):
try:
self.client.bind((self.IPAddress, self.portNumber))
self.client.setblocking(0)
except: print "Cannot connect."
def close(self):
try:
self.client.close()
except:
pass
udpClient = UDPClient("0.0.0.0", 50000)
gui = GUI(udpClient)
gtk.main()
到目前为止,一切都完美地运行。
太简单了,谢谢。 –
@ Jordan.CarrollCS:如果您在后台线程中运行任意GUI代码,则仅添加'gobject.threads_init()'是不够的。看看我提供的例子*它足够了。请阅读[多线程GTK应用程序 - 第1部分:误解](否则请阅读http://blogs.operationaldynamics.com/andrew/software/gnome-desktop/gtk-thread-awareness)。 – jfs
我实施了新的更改。你能解释为什么它“不够”,并验证我是否正确实施了你的建议?我非常感谢你的帮助。 –