简体   繁体   中英

Tornado- how to call a handler in another function

I am currently trying to use Tornado's web-socket handlers to update a dashboard every time a certain function is called. here is the handler:

class WebSocketHandler(websocket.WebSocketHandler):
    clients = []
    def open(self):
        logging.info("WEBSOCKET OPEN")
        WebSocketHandler.clients.append(self)
    def on_message(self, message):
        logging.info("message from websocket recieved")
        self.write_message("WebSocket connected")
    def on_close(self):
        logging.info("WEBSOCKET closed")

and here is the client-side script which connects the WebSocket on load:

  function WebSocketTest()
{ var ws = 0;
   ws = new WebSocket("ws://localhost:8008/WEB");
   ws.onopen = function()
    {
    ws.send("initial connect")
    }

  ws.onmessage = function (evt)
  {
    console.log(evt.data)
  };

  ws.onclose = function()
  {
    console.log("closed ");
  };
}

The websockets connect sucessfully.

i need to call write_message from WebSocketHandler but i'm very confused what the instance of it is? the error i keep running into is that self isn't defined but im not sure what self is exactly? i know that WebSocketHandler gets run whenever the client tries to load ^/WEB$

EDIT: here is my server.py file, i need to call write_message right after the spawn callback call in itercheckers

class Server():



@classmethod
def run(cls):
    options.parse_command_line()
    # Start web
    template_path = os.path.join(os.path.dirname(__file__), 'templates')
    jinja2loader = Jinja2Loader(template_path)
    kwargs = dict(
        template_loader=jinja2loader,
        static_path=os.path.join(os.path.dirname(__file__), 'static'),
        debug=True,
        login_url="/auth/login",
        cookie_secret="dn470h8yedWF9j61BJH2aY701i6UUexx"
    )
    app = web.Application(handlers, **kwargs).listen(
        configuration['server']['port'],)

    # Reset events
    @gen.coroutine
    def reset(parent=None):
        if parent is None:
            parent = configuration
        # Reset event happyness
        yield events.reset_happy(parent)
        # Read last status
        data = yield events.get(parent)
        # Read and set happy from the last status
        happy = (data or {}).get('status', events.STATUS_OK) \
            in events.HAPPY
        yield events.set_happy(parent, happy)
        # Iterate sub-events
        for event in parent['events']:
            yield reset(event)

    ioloop.IOLoop.current().run_sync(reset)



    # Start checkers
    def itercheckers(parent):
        index = 0
        for event in parent.get('events', []):
            if 'checker' in event:
                checker = event['checker']
                p, m = checker['class'].rsplit('.', 1)
                ioloop.IOLoop.current().spawn_callback(
                    getattr(importlib.import_module(p), m)(
                        event=event,
                        frequency=checker.get('frequency', 1),
                        params=checker['params']
                    ).run)
            index += 1
            itercheckers(event)
    itercheckers(configuration)



    # Start alerts
    ioloop.IOLoop.current().run_sync(alerts.reset)
    for alert in configuration['alerts']:
        p, m = alert['class'].rsplit('.', 1)
        ioloop.IOLoop.current().spawn_callback(
            getattr(importlib.import_module(p), m)(
                alert=alert
            ).run
        )

    # Start loop
    ioloop.IOLoop.current().start()

First thing first, self keyword is pointed to current websocket client that is handled in the moment. To use tornado websockets you must initialize tornado app

app = web.Application([
    (r'/ws', WSHandler), #tells it to redirect ws:// to websocket handler
#Choose different names from defaults because of clarity
])

if __name__ == '__main__':
    app.listen(5000) #listen on what port
    ioloop.IOLoop.instance().start()

Then you must have WSHandler class you're pointing websockets trafic to

class WSHandler(websocket.WebSocketHandler):
    #crossdomain connections allowed
    def check_origin(self, origin):
        return True
    #when websocket connection is opened
    def open(self):
       print("Client connected ")

    def on_close(self):
       print("Client disconnected")

    def on_message(self,message):
       self.write_message(message) #echo back whatever client sent you

So complete app would look like

from tornado import websocket, web, ioloop
clients = [] 

#whenever you want to broadcast to all connected call this function
def broadcast_message(msg):
    global clients 
    for client in clients:
        client.write_message(msg)

class WSHandler(websocket.WebSocketHandler):
    #crossdomain connections allowed
    def check_origin(self, origin):
        return True
    #when websocket connection is opened
    def open(self):
       #here you can add clients to your client list if you want
       clients.append(self)
       print("Client connected ")

    def on_close(self):
       clients.remove(self)
       print("Client disconnected")

    def on_message(self,message):
       self.write_message(message) #echo back whatever client sent you

app = web.Application([
    (r'/ws', WSHandler), #tells it to redirect ws:// to websocket handler
#Choose different names from defaults because of clarity
])

if __name__ == '__main__':
    app.listen(5000) #listen on what port
    ioloop.IOLoop.instance().start()

And now to connect to it with js

function WebSocketTest()
{ 
   var ws = new WebSocket("ws://localhost:5000/ws");
    ws.onopen = function()
    {
       ws.send("initial connect")
    }

    ws.onmessage = function (evt)
    {
       console.log(evt.data) 
    };

    ws.onclose = function()
    {
       console.log("closed ");
    };
}

I haven't tested it but should work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM