1

this is probably more a question about threading than about my websocket. I'm using "SimpleWebSocket" from github ( https://github.com/dpallot/simple-websocket-server ) The example works fine:

from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

class SimpleEcho(WebSocket):

    def handleMessage(self):
        # echo message back to client
        self.sendMessage(self.data)

    def handleConnected(self):
        print self.address, 'connected'

    def handleClose(self):
        print self.address, 'closed'

server = SimpleWebSocketServer('', 8000, SimpleEcho)
server.serveforever()

The Server is running, I can connect and send Messages.

Now i try to run it as a Thread with those classes: This one is supposed to create many threads including the WebSocketServer

from websockethread import WebSocketThread
class startManyThreads:
    def __init__(self):
        self.thread1 = WebSocketThread()
        self.thread1.start()

if __name__ == "__main__":
    startManyThreads = startManyThreads()

This class should run as my thread:

import threading
from SimpleWebSocketServer import SimpleWebSocketServer
from webSocketServer import WebSocketServer

class WebSocketThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        server = SimpleWebSocketServer('', 8000, WebSocketServer)
        server.serveforever()

And this is the "customized" echo example:

from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

class SimpleEcho(WebSocket):

    def handleMessage(self):
        # echo message back to client
        self.sendMessage(self.data)

    def handleConnected(self):
        print self.address, 'connected'

    def handleClose(self):
        print self.address, 'closed'

I have also tried to derive this: class SimpleEcho(WebSocket, threading.Thread):

Any Ideas what i'm doing wrong? & Thanks alot in advance!

Edit: The result when i run "simpleEcho" is that i get a prompt can connect via the websocket.html (provided on github), send and receive Messages

The result when i put it in a thread (anyone of the 3 ways i tried) is the same behaviour except when i try to "connect" from the websocket.html i get a "error: undefined". With nmap i checked and the Server seems so be running & listening to port 8000

Edit 2: Derived new Class from SimpleWebSocketServer

import threading

from SimpleWebSocketServer import SimpleWebSocketServer

class ThreadSimpleWebSocketThread(threading.Thread, SimpleWebSocketServer):
    def __init__(self, serversocket):
        threading.Thread.__init__(self)
        self.serversocket = serversocket

    def serveforever(self):
        SimpleWebSocketServer.serversocket = self.serversocket
        SimpleWebSocketServer.selectInterval = 0.1
        SimpleWebSocketServer.listeners = [self.serversocket]
        super(ThreadSimpleWebSocketThread, self).serveforever()

    def run(self):
        self.serveforever()
Markus
  • 55
  • 2
  • 8
  • What is the expected behavior and actual behavior? – merlin2011 Jul 11 '16 at 08:45
  • Expected behaviour would be that i can connect with the "test Client" provided on the github. Actual behaviour is, that i'm getting an "undefined error" (on the test "Homepage") as soon as i run it a as a thread. no Errors elsewhere – Markus Jul 11 '16 at 08:51

1 Answers1

0

The main problem seems to be where you're starting the server. The Thread.__init__() method runs inside the main thread (of the caller), not the actual WebSocketThread(). This needs to be done in the Thread.run() method:

class WebSocketThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        server = SimpleWebSocketServer('', 8000, WebSocketServer)
        server.serveforever()

The code inside run() actually runs inside the thread.

Note that because of the Global Interpreter Lock, threads won't improve performance much, and you'll probably need multiprocessing. However, if you just want to offload the I/O waiting, this should work fine.

Edit: From looking at this GitHub project, and rethinking what you're trying to do, this isn't trivial. You'll have to override WebSocket.serveforever() in your SimpleEcho() class and change it to accept the socket and pass the accepted socket to a Thread (see here).

Will
  • 24,082
  • 14
  • 97
  • 108
  • I use the threads because there is a bunch of other stuff done simultaniously. I already tried this method aswell. From the Python side it Looks like its working (just a blank prompt in the console - like the standalone Version had) but i always get the error in the error "undefined" – Markus Jul 11 '16 at 08:59
  • Can you edit and show the complete code at the bottom after making the fixes here in my answer? – Will Jul 11 '16 at 09:06
  • It is exactly the code above (from my Initial post) and the "WebSocketThread" class is this one from your post (copy & paste). It seems to be running but I cant connect. nmap also Shows me the port 8000 is opend and listening – Markus Jul 11 '16 at 09:13
  • I'm trying to override serverforever() in SimpleEcho. The Problem im having now is that serveforever() is a method of SimpleWebSocketServer and this on is derived from object. the only Connection between SimpleWebSocketServer and WebSocket is the Argument in the constructor of SimpleWebSocketServer. Do i have to Change the serveforver() method to accectp the socket? – Markus Jul 11 '16 at 10:58
  • Sorry, what I should have said, was extend `SimpleWebSocketServer()` to make a `ThreadedSimpleWebSocketServer()` (and use that instead), then override `serveforever()` making it pass the sockets to new threads. – Will Jul 11 '16 at 11:37
  • I tried that now with the same result as above. I create the socket in my main and give it to the ThreadSimpleWebSocketThread(self.serversocket). In the ThreadSimpleWebSocketThread Class i override serveforever and set the SimpleWebSocketServer.serversocket and afterwards run super(ThreadSimpleWebSocketThread, self).serveforever(). Port is again open, application seems to be running but i can not connect – Markus Jul 11 '16 at 12:11
  • Can you show your new code with the new `ThreadedSimpleWebSocket`? – Will Jul 11 '16 at 12:14
  • I edited the original post. I also tried to Access the variables with self.varName in the serveforever() with the same result. e.g. self.selectInterval = 0.1 – Markus Jul 11 '16 at 12:24
  • Ah I see. Unfortunately this will be much more complex. You'll basically have to copy and paste the code from `SimpleWebSocketServer .serveforever()` and change the `accept()` logic to pass the sockets of the accepted connections to a new thread you create each time. – Will Jul 11 '16 at 12:28
  • ok. Tank you for your help. Just one more question for my understanding. once serveforever() is called i will get executed until the Programm is terminated. I'm running a msg-Q (zeroMQ) and want to interact (send & receive Messages) with the zeroMQ and the webapplication which i guess will not work with this Kind of Programm logic – Markus Jul 11 '16 at 12:43