Skip to main content

Working with Tornado WebSockets

Introduction

WebSockets is a protocol that allows bidirectional, persistent communication between a client (typically a web browser) and a server. This makes it an excellent choice for real-time applications like chat apps, multiplayer games, and live data feeds. Tornado, a Python web framework and asynchronous networking library, supports this protocol and makes it relatively easy to work with.

Today, we'll explore how to implement WebSockets in Tornado.

WebSocket Basics

Before we dive into implementation, let's cover some WebSocket basics:

  • WebSocket connections are initiated by the client through a process called "handshaking."
  • Once a WebSocket connection is established, it remains open until either the client or the server decides to close it.
  • This persistent connection allows for continuous, two-way communication.

Setting Up Your Tornado Application

First, let's set up a basic Tornado web application. We'll add WebSocket functionality in the next sections.

import tornado.ioloop
import tornado.web

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

def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])

if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

Adding a WebSocket Handler

To handle WebSocket connections, we need to create a new handler. This handler will inherit from the tornado.websocket.WebSocketHandler class instead of the usual tornado.web.RequestHandler.

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")

def on_message(self, message):
self.write_message("You said: " + message)

def on_close(self):
print("WebSocket closed")

Here, we've defined three methods:

  • open(): Called when a WebSocket is handshaked.
  • on_message(message): Called when the server receives a message from the client.
  • on_close(): Called when the WebSocket is closed.

Adding the WebSocket Route

Next, we need to add a route to our application that points to this handler.

def make_app():
return tornado.web.Application([
(r"/", MainHandler),
(r"/websocket", WebSocketHandler),
])

Testing the WebSocket

Now you can test your WebSocket. There are various tools available online to test WebSockets, or you can create a simple HTML page with JavaScript WebSocket APIs.

Remember, WebSocket URLs start with ws:// or wss:// (for secure WebSockets) instead of http:// or https://.

Broadcasting to Multiple Clients

Often, you'll want to send messages to multiple connected clients. To do this, we can keep track of connected clients in a set and write to all of them:

class WebSocketHandler(tornado.websocket.WebSocketHandler):
clients = set()

def open(self):
self.clients.add(self)
print("WebSocket opened")

def on_message(self, message):
for client in self.clients:
client.write_message("Someone said: " + message)

def on_close(self):
self.clients.remove(self)
print("WebSocket closed")

Closing Thoughts

This is a basic introduction to working with WebSockets in Tornado. Real-world applications might need to handle more complex scenarios, like error handling, connection timeouts, and security/authentication. But with this foundation, you're well on your way to creating real-time, interactive web applications.