以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可。

如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用tornado,以下是一个基于tornado的rest的应用简介。

当我们下载好了tornado以后,可以按照tornado的文档demo,复制一份监听代码过来,代码如下:

  1. import tornado.ioloop
  2. import tornado.web
  3.  
  4. class MainHandler(tornado.web.RequestHandler):
  5. def get(self):
  6. self.write("Hello, world")
  7.  
  8. application = tornado.web.Application([
  9. (r"/", MainHandler),
  10. ])
  11.  
  12. if __name__ == "__main__":
  13. application.listen(8888)
  14. tornado.ioloop.IOLoop.instance().start()

这一段代码在运行时就已经可以开始监听并返回信息了,然后开始按照rest的规范开始改写,我们首先需要对url的path进行定位,根据path执行相对应的代码,则有了以下代码:

  1. import os.path
  2. import tornado.escape
  3. import tornado.ioloop
  4. import tornado.options
  5. import tornado.web
  6. import tornado.websocket
  7. import tornado.httpserver
  8. import tools
  9. import applogic
  10. from config import config
  11.  
  12. class Application(tornado.web.Application):
  13. def __init__(self):
  14. handlers = [
  15. (r"/.*?", WebHandler),
  16. ]
  17. settings = dict(
  18. cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
  19. template_path=os.path.join(os.path.dirname(__file__), "templates"),
  20. static_path=os.path.join(os.path.dirname(__file__), "static"),
  21. xsrf_cookies=False
  22. )
  23. tornado.web.Application.__init__(self, handlers, **settings)
  24.  
  25. class WebHandler(tornado.web.RequestHandler):
  26. def get(self):
  27. path = self.request.path
  28. command = path[path.rfind('/') +1:]
  29. result = applogic.execute(self, command, self.get_argument)
  30. if result:
  31. to_message = tools.dumps(result)
  32. self.write(to_message)
  33.  
  34. def post(self):
  35. path = self.request.path
  36. command = path[path.rfind('/') +1:]
  37. obj = tools.loads(self.request.body)
  38. result = applogic.execute(self, command, obj)
  39. if result:
  40. to_message = tools.dumps(result)
  41. self.write(to_message)
  42.  
  43. def main():
  44. app = Application()
  45. http_server = tornado.httpserver.HTTPServer(app)
  46. http_server.bind(config.default['main_port'], config.default['host'])
  47. tornado.ioloop.IOLoop.instance().start()

我们对path做了最后一级目录的截取,由于客观原因,多级目录的则需要看客们自行实现。

applogic是我们的具体的逻辑代码门面类,因为是脚本语言的关系,所以这里使用一个相对巧妙的ioc,代码如下:

  1. def execute(handler, command, obj):
  2. if main_map.has_key(command):
  3. result = main_map[command](handler, obj)
  4. if result:
  5. response.send(handler, result)
  6. else:
  7. handler.send_error(404)
  8.  
  9. def create(handler, obj):
  10. flag = papercache.push(obj)
  11. result = {}
  12. if flag:
  13. result = {
  14. 'code':0
  15. }
  16. else:
  17. result = {
  18. 'code':1,
  19. 'errorMsg':'param is error'
  20. }
  21. return result
  22.  
  23. def grab(handler, obj):
  24. id = obj.has_key('id') and obj['id'] or None
  25. result = {
  26. 'code':1,
  27. 'errorMsg':'redpaper is empty',
  28. 'money':0
  29. }
  30. if id:
  31. money = papercache.pop_queue(id)
  32. if money:
  33. result = {
  34. 'money' : money,
  35. 'code': 0
  36. }
  37. return result
  38.  
  39. main_map = {
  40. 'create':create,
  41. 'grab':grab
  42. }

我们将具体的执行逻辑,放在定义好的function里面,然后将function的引用放在一个字典里面,然后根据command(最后一级目录对应的字符串),来执行具体的代码。

我们将返回的数据做了一个封装,因为实际应用里面的数据格式,可能采用的是json,或者是其它自定义的协议,所以我们有一个response的封装,代码如下:

  1. def send(handler, obj):
  2. if type(handler) is not None:
  3. obj = tools.dumps(obj)
  4. handler.write(obj)

tools的代码如下:

  1. import json
  2.  
  3. def dumps(obj):
  4. obj = toUnicode(obj)
  5. if obj:
  6. obj = json.dumps(obj)
  7. obj = str(obj)
  8. return obj
  9.  
  10. def loads(obj):
  11. if obj:
  12. obj = json.loads(str(obj))
  13. obj = toUtf8(obj)
  14. return obj

因为可能存在中文的关系,所以加了一个Utf8的转换,,基于websocket的也是同理,则在监听的时候,使用WebSocketHandle,代码如下:

  1. import os.path
  2. import tornado.escape
  3. import tornado.ioloop
  4. import tornado.options
  5. import tornado.web
  6. import tornado.websocket
  7. import tornado.httpserver
  8. import tools
  9. import applogic
  10. from config import config
  11.  
  12. class Application(tornado.web.Application):
  13. def __init__(self):
  14. handlers = [
  15. (r"/web", MainHandler)
  16. (r"/.*?", WebHandler),
  17. ]
  18. settings = dict(
  19. cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
  20. template_path=os.path.join(os.path.dirname(__file__), "templates"),
  21. static_path=os.path.join(os.path.dirname(__file__), "static"),
  22. xsrf_cookies=False
  23. )
  24. tornado.web.Application.__init__(self, handlers, **settings)
  25.  
  26. class MainHandler(tornado.websocket.WebSocketHandler):
  27. def allow_draft76(self):
  28. return True
  29.  
  30. def open(self):
  31. token = self.get_cookie('token')
  32. if not token:
  33. print "long not token"
  34. self.close()
  35. else:
  36. print('connect')
  37.  
  38. def on_close(self):
  39. print('close');
  40.  
  41. def on_message(self, message):
  42. obj = tools.loads(message)
  43. command = obj.has_key('command') and obj['command'] or None
  44. body = obj.has_key('body') and obj['body'] or None
  45. result = applogic.execute(self, command, body)
  46. if result:
  47. to_message = tools.dumps(result)
  48. self.write(to_message)
  49. return
  50.  
  51. class WebHandler(tornado.web.RequestHandler):
  52. def get(self):
  53. path = self.request.path
  54. command = path[path.rfind('/') +1:]
  55. result = applogic.execute(self, command, self.get_argument)
  56. if result:
  57. to_message = tools.dumps(result)
  58. self.write(to_message)
  59.  
  60. def post(self):
  61. path = self.request.path
  62. command = path[path.rfind('/') +1:]
  63. obj = tools.loads(self.request.body)
  64. result = applogic.execute(self, command, obj)
  65. if result:
  66. to_message = tools.dumps(result)
  67. self.write(to_message)
  68.  
  69. def main():
  70. app = Application()
  71. http_server = tornado.httpserver.HTTPServer(app)
  72. http_server.bind(config.default['main_port'], config.default['host'])
  73. tornado.ioloop.IOLoop.instance().start()

可能你们会觉得怎么多了个command和body出来了,因为我的通讯协议是假定{"command":"", "body":""},这样的json格式。

那一个简易的基于python的rest服务和websocket通讯服务器到这里就结束了

使用tornado,我们可以做什么?的更多相关文章

  1. Tornado基于MiddleWare做中间件

    详细代码如下: 在app.py里添加 # -*- coding:utf-8 -*- from tornado.ioloop import IOLoop from tornado.web import ...

  2. 深入理解Tornado——一个异步web服务器

    本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...

  3. [tornado]websocket 最简单demo

    想法 前两天想看看django 长轮询或者是websocket的方案,发现都不太好使. tornado很适合做这个工作,于是找了些资料,参照了做了个最简单demo,以便备用. 具体的概念就不说了,to ...

  4. tornado架构分析1 从helloworld分析tornado架构

    最近公司需要我写一个高性能RESTful服务组件.我之前很少涉及这种高性能服务器架构,帮公司和平时没事玩都是写脚本级别的东西.虽然好多基础组件(sphinx.logging.configparse等) ...

  5. Python的Tornado框架的异步任务与AsyncHTTPClient 

    转载自http://www.php.cn/python-tutorials-284773.html 高性能服务器TornadoPython的web框架名目繁多,各有千秋.正如光荣属于希腊,伟大属于罗马 ...

  6. python的高性能web应用的开发与测试实验

    python的高性能web应用的开发与测试实验 tornado“同步和异步”网络IO模型实验 引言 python语言一直以开发效率高著称,被广泛地应用于自动化领域: 测试自动化 运维自动化 构建发布自 ...

  7. 一个使用 asyncio 开发的网络爬虫(译文)

    原文地址:https://www.aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html 作者简介 A. Jesse Jiryu ...

  8. tornado做简单socket服务器(TCP)

    http://blog.csdn.net/chenggong2dm/article/details/9041181 服务器端代码如下: #! /usr/bin/env python #coding=u ...

  9. tornado框架学习及借用有道翻译api做自动翻译页面

    趁着这几天有时间,就简单的学了一下tornado框架,简单做了个自动翻译的页面 仅为自己学习参考,不作其他用途 文件夹目录结构如下: . ├── server.py ├── static │   └─ ...

随机推荐

  1. Android UI体验之全屏沉浸式透明状态栏效果

    前言: Android 4.4之后谷歌提供了沉浸式全屏体验, 在沉浸式全屏模式下, 状态栏. 虚拟按键动态隐藏, 应用可以使用完整的屏幕空间, 按照 Google 的说法, 给用户一种 身临其境 的体 ...

  2. 【前端性能】高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  3. WinForm 天猫2013双11自动抢红包【源码下载】

    1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...

  4. 【.net 深呼吸】程序集的热更新

    当一个程序集被加载使用的时候,出于数据的完整性和安全性考虑,程序集文件(在99.9998%的情况下是.dll文件)会被锁定,如果此时你想更新程序集(实际上是替换dll文件),是不可以操作的,这时你得把 ...

  5. javascript匹配各种括号书写是否正确

    今天在codewars上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...

  6. ASP.NET 5 RC1 升级 ASP.NET Core 1.0 RC2 记录

    升级文档: Migrating from DNX to .NET Core Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0 RC2 Migrating ...

  7. Android之网络数据存储

    一.网络保存数据介绍 可以使用网络来保存数据,在需要的时候从网络上获取数据,进而显示在App中. 用网络保存数据的方法有很多种,对于不同的网络数据采用不同的上传与获取方法. 本文利用LeanCloud ...

  8. Spring异步功能

    使用 Spring 的异步功能时,实质是使用的 Servlet3 及以上版本的异步功能. Spring 的异步处理机制需要在 web.xml 中全部的 servlet 和 filter 处配置 < ...

  9. Maven(一)linux下安装

    1.检查是否安装JDK,并且设置了环境变量(JAVA_HOME): echo $JAVA_HOME java -version 运行结果: 显示jdk的安装路径,和java的版本,如: #jdk路径 ...

  10. gulp 自动添加版本号

    本文介绍利用 gulp-rev 和 gulp-rev-collector 进行版本管理 npm官网介绍使用后的效果如下: "/css/style.css" => " ...