Socket server not responding when in thread
Question: I'm trying to set up a simple socket server in a qgis plugin. The ultimate
goal is to communicate between qgis and matlab.

I found a clear example for something comparable from here:
<http://www.blog.pythonlibrary.org/2013/06/27/wxpython-how-to-communicate-
with-your-gui-via-sockets/>

When implemented it seems to hang at self.socket.accept() even when a client
connects with it. The connection is established (tried with matlab and python)
but I don't receive anything. Netstat shows that there is a server listening
at the correct port.

Here's the relevant code:

    
    
    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
    

In the log I can see the "Waiting for connection" message but it never passes
"Connected to client". I tried implementing it without threading (remove
threading, setDaemon and start()->run())and it does actually work then.
However the gui obviously freezes then so that's not an option.

Edit:

I removed the select, which was indeed stalling the process, and only close
the client socket. Here's the standalone code for the server:

    
    
    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")
    

And client:

    
    
    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()
    

Standalone this now does what I wanted it to do :). Unfortunately after
implementing the changes in the qgis plugin the same problem still occurs. I
suppose the problem lies with qgis then and how it handles separate threads.


Answer: I'm only guessing here, but my guess is that the client doesn't send anything
until your server sends something first. If that's the case then the `select`
call will timeout, and you go back to call `accept` _again_ which will block
forever (or until you connect with another client).

My advice is that you should skip the `select` call.

* * *

Also, after you close connection to the client you also close the _listening_
socket, so no more client can connect.

