2014-09-30 54 views
0

我試圖在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顯然凍結了,所以這不是一個選項。

編輯:

我刪除了選擇,這的確是拖延的過程,只有關閉客戶端套接字。 這裏是服務器的獨立代碼:

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

試着做一個示例程序,在隔離工作,我們可以獨立運作。 – 2014-09-30 08:05:42

回答

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 
0

我只是在這裏猜測,但我的猜測是客戶端不會發送任何東西,直到您的服務器首先發送一些東西。如果是這種情況,那麼select呼叫將超時,並且您將再次呼叫accept再次這將永遠阻塞(或直到您連接到另一個客戶端)。

我的建議是,你應該跳過select電話。


而且,以後你的客戶密切聯繫,你也關閉插座,所以沒有更多的客戶端連接。

+0

謝謝,解決了部分問題。另一部分似乎是qgis。 – Mako 2014-09-30 10:42:50

相關問題