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.