Search code examples
javascripttornado

Hello world with Tornado and Javascript client


I would like to establish a simple two-way communication between a Tornado server and a Javascript client.

When I run the server, followed by opening the page, the server prints out "get" as expected. However, while the server sends something back, the onmessage event never seems to be triggered in the client. Moreover, the Javascript console produces the following error:

WebSocket connection to 'ws://localhost:8888/' failed: Error during WebSocket handshake: Unexpected response code: 200

I have no clue what I am doing wrong here.

Python server (tornadoserver.py):

import tornado.ioloop
import tornado.web

class Hello(tornado.web.RequestHandler):
    def get(self):
        print("get")
        self.write("Hello, world")
        self.flush()


application = tornado.web.Application([
    (r"/", Hello),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

Javascript client (tornado.html):

<script>
ws = new WebSocket("ws://localhost:8888/");
ws.onmessage = function(e) {
    alert('message received: ' + e.data);
};
</script>

Solution

  • You need a separate WebSocketHandler instance mapped to a separate URL in your application. So your "tornado.html" should be mapped to the URL "/", and your Javascript should connect to a WebSocketHandler listening on a URL like "/websocket". Try this:

    import tornado.ioloop
    import tornado.web
    import tornado.websocket
    
    
    class Hello(tornado.websocket.WebSocketHandler):
        def open(self):
            self.write_message("Hello, world")
    
        def on_message(self, message):
            pass
    
        def on_close(self):
            pass
    
    
    class Main(tornado.web.RequestHandler):
        def get(self):
            # This could be a template, too.
            self.write('''
    <script>
    ws = new WebSocket("ws://localhost:8888/websocket");
    ws.onmessage = function(e) {
        alert('message received: ' + e.data);
    };
    </script>''')
    
    
    application = tornado.web.Application([
        (r"/", Main),
        (r"/websocket", Hello),
    ])
    
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()