ioloop.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import tornado.websocket
  2. import time, json
  3. from collections import defaultdict, OrderedDict
  4. from .framework import Global, Msg, Task
  5. from os.path import abspath, dirname
  6. from tornado.web import StaticFileHandler
  7. from tornado.gen import coroutine, sleep
  8. from tornado.log import gen_log
  9. import logging
  10. project_dir = dirname(abspath(__file__))
  11. def start_ioloop(coro_func, port=8080):
  12. class EchoWebSocket(tornado.websocket.WebSocketHandler):
  13. def check_origin(self, origin):
  14. return True
  15. def get_compression_options(self):
  16. # Non-None enables compression with default options.
  17. return {}
  18. @coroutine
  19. def open(self):
  20. print("WebSocket opened")
  21. self.set_nodelay(True)
  22. ############
  23. self.coros = {} # coro_id -> coro
  24. self.callbacks = OrderedDict() # UI元素时的回调, key -> callback, mark_id
  25. self.mark2id = {} # mark_name -> mark_id
  26. self._closed = False
  27. self.inactive_coro_instances = [] # 待激活的协程实例列表
  28. self.main_task = Task(coro_func(), ws=self)
  29. self.coros[self.main_task.coro_id] = self.main_task
  30. self.step_task(self.main_task)
  31. def step_task(self, task, result=None):
  32. task.step(result)
  33. if task.task_finished:
  34. gen_log.debug('del self.coros[%s]', task.coro_id)
  35. del self.coros[task.coro_id]
  36. while self.inactive_coro_instances:
  37. coro = self.inactive_coro_instances.pop()
  38. task = Task(coro, ws=self)
  39. self.coros[task.coro_id] = task
  40. task.step()
  41. if self.coros[task.coro_id].task_finished:
  42. gen_log.debug('del self.coros[%s]', task.coro_id)
  43. del self.coros[task.coro_id]
  44. if self.main_task.task_finished:
  45. for t in self.coros:
  46. t.cancel()
  47. self.close()
  48. def on_message(self, message):
  49. print('on_message', message)
  50. # { event:, coro_id:, data: }
  51. data = json.loads(message)
  52. coro_id = data['coro_id']
  53. coro = self.coros.get(coro_id)
  54. if not coro_id:
  55. gen_log.error('coro not found, coro_id:%s', coro_id)
  56. return
  57. self.step_task(coro, data)
  58. def on_close(self):
  59. self._closed = True
  60. print("WebSocket closed")
  61. def closed(self):
  62. return self._closed
  63. handlers = [(r"/test", EchoWebSocket),
  64. (r"/(.*)", StaticFileHandler,
  65. {"path": '%s/html/' % project_dir,
  66. 'default_filename': 'index.html'})]
  67. gen_log.setLevel(logging.DEBUG)
  68. app = tornado.web.Application(handlers=handlers, debug=True)
  69. http_server = tornado.httpserver.HTTPServer(app)
  70. http_server.listen(port)
  71. print('Open http://localhost:%s/ in Web browser' % port)
  72. tornado.ioloop.IOLoop.instance().start()