我正在尝试在qgis插件中设置一个简单的套接字服务器。最终目标是在qgis和matlab之间进行通信。
我找到了一个明显的例子来说明这里可比的东西: http://www.blog.pythonlibrary.org/2013/06/27/wxpython-how-to-communicate-with-your-gui-via-sockets/
实现时,即使客户端连接它,它似乎也会挂在self.socket.accept()上。建立连接(尝试使用matlab和python)但我没有收到任何东西。 Netstat显示有一个服务器正在侦听正确的端口。
以下是相关代码:
class SocketServerListen(threading.Thread):
def __init__(self):
host = "127.0.0.1"
port = 22001
QgsMessageLog.logMessage("Initializing server")
threading.Thread.__init__(self)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((host, port))
self.socket.listen(5)
self.setDaemon(True)
self.start()
def run(self):
while True:
try:
QgsMessageLog.logMessage("Waiting for connection")
conn, address = self.socket.accept()
ready = select.select([conn,],[], [],2)
if ready[0]:
conn.sendall("hello")
QgsMessageLog.logMessage("Connected to client")
time.sleep(0.5)
#receive header and message
message = conn.recv(512)
#disconnect connection
QgsMessageLog.logMessage("Message:" + message)
self.socket.shutdown(socket.SHUT_RDWR)
conn.close()
self.socket.close()
break
except socket.error, msg:
print "Socket error! %s" % msg
break
在日志中,我可以看到“等待连接”消息,但它从未通过“已连接到客户端”。 我尝试在没有线程的情况下实现它(删除线程,setDaemon和start() - > run())然后它确实有效。然而,gui显然会冻结,所以这不是一个选择。
编辑:
我删除了select,这确实拖延了进程,只关闭了客户端套接字。 这是服务器的独立代码:
import threading
import socket
import time
import select
class SocketServerListen(threading.Thread):#threading.Thread
def __init__(self):
host = "127.0.0.1"
port = 22001
print("Initializing server")
threading.Thread.__init__(self)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((host, port))
self.socket.listen(5)
self.setDaemon(True)
self.start()
def run(self):
while True:
try:
print("Waiting for connection")
conn, address = self.socket.accept()
conn.sendall("hello")
print("Connected to client")
time.sleep(0.5)
#receive message
message = conn.recv(512)
print(message)
#disconnect connection
conn.close()
#self.socket.close()
#break
except socket.error, msg:
print("Socket error! %s"),msg
break
listenIncoming = SocketServerListen()
for i in range(0,10):
time.sleep(5)
print("doing other stuff")
print("end")
客户:
import socket
host = "127.0.0.1"
port = 22001
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host,port))
message = client.recv(512)
print("Message:" + message)
client.sendall("hiya")
client.shutdown(socket.SHUT_RDWR)
client.close()
独立这个现在可以做我想做的事:)。不幸的是,在实现qgis插件中的更改后仍然会出现同样的问题。我想问题就在于qgis以及它如何处理单独的线程。
答案 0 :(得分:0)
我只是在这里猜测,但我的猜测是,在您的服务器首先发送内容之前,客户端不会发送任何内容。如果是这种情况,则select
来电将超时,然后您再次致电accept
,这将永久阻止(或直到您与其他客户端连接) )。
我的建议是你应该跳过select
电话。
此外,在关闭与客户端的连接后,您还会关闭监听套接字,因此不再有客户端可以连接。
答案 1 :(得分:0)
似乎问题是QGis,或更准确地说PyQT已经有某种线程implemented。我不能说我完全理解它,但它可以解决问题:
工人阶级:
class SocketServerListen(QObject):
def __init__(self):
QObject.__init__(self)
host = "127.0.0.1"
port = 22001
QgsMessageLog.logMessage("Initializing server")
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((host, port))
self.socket.listen(5)
def run(self):
while True:
try:
QgsMessageLog.logMessage("Waiting for connection")
conn, address = self.socket.accept()
QgsMessageLog.logMessage("Connected to client")
#receive header and message
time.sleep(1)
lengthMessage = conn.recv(4)
message = conn.recv(int(lengthMessage))
QgsMessageLog.logMessage("Message:" + message)
conn.close()
except socket.error, msg:
print "Socket error! %s" % msg
break
def kill(self):
self.killed = True
finished = pyqtSignal(object)
error = pyqtSignal(Exception,basestring)
progress = pyqtSignal(float)
运行它的代码:
def run(self):
worker = SocketServerListen()
thread = QThread()
worker.moveToThread(thread)
worker.finished.connect(self.workerFinished)
worker.error.connect(self.workerError)
thread.started.connect(worker.run)
thread.start()
thread.exec_()
self.thread = thread
self.worker = worker