I'm very new to Tornado and wanted to know if it is possible to send a message (write_message) at will from within my Python program to all clients? For example, say my program is monitoring a directory to see if a file appears/exists. When it appears, I want to send a web socket message to a browser client that the file exists. I can't seem to understand how to invoke the "write_message" method without first receiving a websocket message (on_message handler.)
Even if I use the "PeriodicCallback" method, I'm still unclear as to how I actually call the "write_message" method. Are there any examples out there of how to invoke "write_message" without doing it within the "on_message" handler?
If you map the handler above to /websocket in your application, you can invoke it in JavaScript with: var ws = new WebSocket("ws://localhost:8888/websocket"); ws. onopen = function() { ws. send("Hello, world"); }; ws.
Messages sent by the server to the client can include plain text messages, binary data, or images. Whenever data is sent, the onmessage function is fired. This event acts as a client's ear to the server. Whenever the server sends data, the onmessage event gets fired.
All messages are delivered to subscribers in order until the WebSockets connection drops.
You need to keep a collection of openned websockets and iterate through that collection at will to send messages.
As an example, I'll send a message anytime a client connect to your.domain.example/test/
but the idea is the same whenever you want to send something:
import os.path
import logging
from tornado import ioloop, web, websocket
SERVER_FOLDER = os.path.abspath(os.path.dirname(__file__))
LOGGER = logging.getLogger('tornado.application')
class TestHandler(web.RequestHandler):
def get(self):
server = ioloop.IOLoop.current()
data = "whatever"
server.add_callback(DefaultWebSocket.send_message, data)
self.set_status(200)
self.finish()
class DefaultWebSocket(websocket.WebSocketHandler):
live_web_sockets = set()
def open(self):
LOGGER.debug("WebSocket opened")
self.set_nodelay(True)
self.live_web_sockets.add(self)
self.write_message("you've been connected. Congratz.")
def on_message(self, message):
LOGGER.debug('Message incomming: %s', message)
def on_close(self):
LOGGER.debug("WebSocket closed")
@classmethod
def send_message(cls, message):
removable = set()
for ws in cls.live_web_sockets:
if not ws.ws_connection or not ws.ws_connection.stream.socket:
removable.add(ws)
else:
ws.write_message(message)
for ws in removable:
cls.live_web_sockets.remove(ws)
def serve_forever(port=80, address=''):
application = web.Application([
(r"/test/", TestHandler),
(r"/websocket/", DefaultWebSocket),
...
],
static_path=os.path.join(SERVER_FOLDER, ...),
debug=True,
)
application.listen(port, address)
LOGGER.debug(
'Server listening at http://%s:%d/',
address or 'localhost', port)
ioloop.IOLoop.current().start()
if __name__ == "__main__":
serve_forever()
You'll obviously need to create a websocket in the browser using the following JavaScript:
socket = new WebSocket('ws://your.domain.example:80/websocket/');
And manage it accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With