ioloop.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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.inactive_coro_instances = [] # 待激活的协程实例列表
  27. # self.tornado_coro_instances = [] # 待执行的tornado coro列表
  28. task = Task(coro_func(), ws=self)
  29. self.coros[task.coro_id] = task
  30. yield task.step()
  31. if task.task_finished:
  32. gen_log.debug('del self.coros[%s]', task.coro_id)
  33. del self.coros[task.coro_id]
  34. yield self.after_step()
  35. @coroutine
  36. def after_step(self):
  37. while self.inactive_coro_instances:
  38. coro = self.inactive_coro_instances.pop()
  39. task = Task(coro, ws=self)
  40. self.coros[task.coro_id] = task
  41. yield task.step()
  42. if self.coros[task.coro_id].task_finished:
  43. gen_log.debug('del self.coros[%s]', task.coro_id)
  44. del self.coros[task.coro_id]
  45. # yield self.after_step()
  46. # while self.tornado_coro_instances:
  47. # yield self.tornado_coro_instances.pop()
  48. @coroutine
  49. def on_message(self, message):
  50. print('on_message', message)
  51. # { event:, coro_id:, data: }
  52. data = json.loads(message)
  53. coro_id = data['coro_id']
  54. coro = self.coros.get(coro_id)
  55. if not coro_id:
  56. gen_log.error('coro not found, coro_id:%s', coro_id)
  57. return
  58. yield coro.step(data)
  59. if coro.task_finished:
  60. gen_log.debug('del self.coros[%s]', coro_id)
  61. del self.coros[coro_id]
  62. yield self.after_step()
  63. if not self.coros:
  64. self.close()
  65. def on_close(self):
  66. print("WebSocket closed")
  67. handlers = [(r"/test", EchoWebSocket),
  68. (r"/(.*)", StaticFileHandler,
  69. {"path": '%s/html/' % project_dir,
  70. 'default_filename': 'index.html'})]
  71. gen_log.setLevel(logging.DEBUG)
  72. app = tornado.web.Application(handlers=handlers, debug=True)
  73. http_server = tornado.httpserver.HTTPServer(app)
  74. http_server.listen(port)
  75. print('Open http://localhost:%s/ in Web browser' % port)
  76. tornado.ioloop.IOLoop.instance().start()