python - обрабатывать торнадо в цикле while - PullRequest
0 голосов
/ 11 мая 2018

У меня есть сервер, на котором выполняется цикл, который читает данные с устройства, и я хочу отправить их всем клиентам, которые подключаются через веб-сокет на торнадо. Я попытался поместить цикл в функцию open, но затем он не может обработать функцию on_close или новые соединения.

Какая лучшая практика для этого?

#!/usr/bin/env python

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import socket

class MyWebSocketServer(tornado.websocket.WebSocketHandler):
    def open(self):
        print('new connection'+self.request.remote_ip)
        try:
            while True:
                '''
                read and send data
                '''
        except Exception,error:
            print "Error on Main: "+str(error)

    def on_close(self):
        print('connection closed'+self.request.remote_ip)

application=tornado.web.Application([(r'/ws',MyWebSocketServer),])

if __name__=="__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8000)
    print('start')
    tornado.ioloop.IOLoop.instance().start()

Спасибо

1 Ответ

0 голосов
/ 12 мая 2018

Вот полный пример запуска кода блокировки в отдельном потоке и рассылки сообщений всем подключенным клиентам.

...

from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=1) # spawn only 1 thread


class MyWebSocketServer(tornado.websocket.WebSocketHandler):
    connections = set() # create a set to hold connections

    def open(self):
        # put the new connection in connections set
        self.connections.add(self)

    def on_close(self):
        print('connection closed'+self.request.remote_ip)
        print('new connection'+self.request.remote_ip)
        # remove client from connections
        self.connections.remove(self)

    @classmethod
    def send_message(cls, msg):
        for client in cls.connections:
            client.write_message(msg)


def read_from_serial(loop, msg_callback):
    """This function will read from serial 
    and will run in aseparate thread

    `loop` is the IOLoop instance
    `msg_allback` is the function that will be 
    called when new data is available from usb
    """
    while True:
        # your code ...
        # ...
        # when you get new data
        # tell the IOLoop to schedule `msg_callback`
        # to send the data to all clients

        data = "new data"
        loop.add_callback(msg_callback, data)

...

if __name__ == '__main__':
    loop = tornado.ioloop.IOLoop.current()

    msg_callback = MyWebSocketServer.send_message

    # run `read_from_serial` in another thread
    executor.submit(read_from_serial, loop, msg_callback)

    ...

    loop.start()
...