套接字服务器在线程中没有响应

时间:2014-09-30 08:00:32

标签: python multithreading sockets qgis

我正在尝试在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以及它如何处理单独的线程。

2 个答案:

答案 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