user3732793
user3732793

Reputation: 1979

Tornado coroutine with websockets not working with python3

The HandlerWebsockets does work fine and is just replying with what has been send at the moment throught messageToSockets(msg). However both tries to send messages to the websocket from the coroutine of the web application are not working. Looks like everything is blocked by these attempts...

class webApplication(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', HandlerIndexPage),
            (r'/websocket', HandlerWebSocket, dict(msg='start')),
        ]

        settings = {
            'template_path': 'templates'
        }
        tornado.web.Application.__init__(self, handlers, **settings)

    @gen.coroutine
    def generateMessageToSockets(self):
        while True:
            msg = str(randint(0, 100))
            print ('new messageToCon: ', msg)
            yield [con.write_message(msg) for con in HandlerWebSocket.connections]
            yield gen.sleep(1.0)

if __name__ == '__main__':

    ws_app = webApplication()
    server = tornado.httpserver.HTTPServer(ws_app)
    port = 9090
    print('Listening on port:' + str(port))
    server.listen(port)
    IOLoop.current().spawn_callback(webApplication.generateMessageToSockets)
    IOLoop.current().set_blocking_log_threshold(0.5)
    IOLoop.instance().start()

Here the WebSockets Handler

class HandlerWebSocket(tornado.websocket.WebSocketHandler):
    connections = set()

    def initialize(self, msg):
        print('HWS:' + msg)

    def messageToSockets(self, msg):
        print ('return message: ', msg)
        [con.write_message(msg) for con in self.connections]

    def open(self):
            self.connections.add(self)
            print ('new connection was opened')
            pass

    def on_message(self, message):
            print ('from WebSocket: ', message)
            self.messageToSockets(message)

    def on_close(self):
            self.connections.remove(self)
            print ('connection closed')
            pass

I am a bit lost in the examples, questions here, documentation etc. So any hint how to properly start a continous calling websocket routine is greatly appreciated

Upvotes: 0

Views: 406

Answers (2)

user3732793
user3732793

Reputation: 1979

unfortunately all the gen.routines tries didn't work for me. Moved back to threads

def generateMessageToSockets():
    while True:
        msg = str(randint(0, 100))
        print ('new messageToCon: ', msg)
        [con.write_message(msg) for con in HandlerWebSocket.connections]
        sleep(1.0)


class WebApplication(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', HandlerIndexPage),
            (r'/websocket', HandlerWebSocket, dict(msg='start')),
        ]

        settings = {
            'template_path': 'templates'
        }
        tornado.web.Application.__init__(self, handlers, **settings)

if __name__ == '__main__':
    tGenarate =  threading.Thread(target=generateMessageToSockets)
    tGenarate.start()
    ws_app = WebApplication()
    server = tornado.httpserver.HTTPServer(ws_app)
    port = 9090
    print('Listening on port:' + str(port))
    server.listen(port)
    ioloop.IOLoop.instance().start()

which works

Upvotes: 1

Ben Darnell
Ben Darnell

Reputation: 22154

generateMessageToSockets will loop endlessly, generating messages as fast as it can without waiting for those messages to be sent. Since it starts first and never yields, the HTTPServer will never actually be able to accept a connection.

If you really want to send messages as fast as you can, the minimal solution without blocking would be

yield [con.write_message(msg) for con in HandlerWebSocket.connections]
yield gen.moment

But it would probably be better to use gen.sleep to send messages at regular intervals, instead of "as fast as possible".

Upvotes: 1

Related Questions