Tornado简单使用

Tornado简单使用

1 介绍

Tornado 是一个基于Python的Web服务框架和 异步网络库,它最初由 FriendFeed 开发,后来被 Facebook 收购并开源,通过利用非阻塞网络 I/O, Tornado 可以承载成千上万的活动连接,完美的实现了 长连接、WebSockets, 和其他对于每一位用户来说需要长连接的程序.

# 官网地址
https://www.tornadoweb.org/en/stable/# 多进程文档
https://www.tornadoweb.org/en/stable/httpserver.html## 安装Tornado
pip install tornado==6.3.3 -i https://pypi.tuna.tsinghua.edu.cn/simple# 原生Websocket标准
https://websockets.spec.whatwg.org/

2 简单使用

helloword.py

import asyncio
import tornadoclass MainHandler(tornado.web.RequestHandler):def get(self):self.write("Hello, world")def make_app():return tornado.web.Application([(r"/", MainHandler),])async def main():app = make_app()app.listen(8888)await asyncio.Event().wait()if __name__ == "__main__":asyncio.run(main())

请求地址

# 地址
http://127.0.0.1:8888/# 返回值
Hello, world

3 简单Web工程

3.1 Python代码

工程目录

在这里插入图片描述

base_web_handler.py

import loggingimport tornado
from tornado.escape import json_decode, to_unicodeclass BaseHandler(tornado.web.RequestHandler):# def set_default_headers(self):# 设置参数# passdef get_json_argument(self, name, default=None):# 解析参数args = {}try:args = json_decode(self.request.body)except Exception as e:logging.info("json is error")pass# 编码数据name = to_unicode(name)# 解析参数if name in args:return args[name]elif default is not None:return defaultelse:# 通知参数异常raise tornado.web.MissingArgumentError(name)

message_handler.py

import tornado.websocketclass MessageWebSocket(tornado.websocket.WebSocketHandler):# 验证连接def check_origin(self, origin):# 用于验证跨域(cross-origin requests)print(origin)# 返回true才能连接,返回false不能连接return Truedef open(self):# 建立连接print("WebSocket opened")def on_message(self, message):print("Received message:", message)self.write_message("Received message:" + "zhonguodoe")passdef on_close(self):print("WebSocket closed")

form_handler.py

from config.base_web_handler import BaseHandlerclass FormHandler(BaseHandler):def get(self):# 获取表单参数print(self.get_arguments("name"))print(self.get_argument("name"))print(self.get_body_arguments("name"))print(self.get_body_argument("name"))self.write("Hello, world")

json_handler.py

from config.base_web_handler import BaseHandlerclass JsonHandler(BaseHandler):# post方法def post(self):# 获取body参数# 注意:Tornado本身没有将body解析json的方法,下面方法是自己封装的BaseHandler中构建的print(self.get_json_argument("data"))self.write("Hello, world")

sse_handler.py

import asynciofrom tornado import genfrom config.base_web_handler import BaseHandlerclass SseHandler(BaseHandler):def set_default_headers(self):# 设置为事件驱动模式self.set_header('Content-Type', "text/event-stream")# 不使用缓存self.set_header('Content-Control', "no-cache")# 保持长连接self.set_header('Connection', "keep-alive")# 允许跨域self.set_header('Access-Control-Allow-Origin', "*")# 使用协程调度实现并发@gen.coroutinedef get(self):# 使用生成器来发送数据流for i in range(3):self.write(self.build_message("test" + str(i)))yield asyncio.sleep(1)print("test1" + str(i))# 发送数据并在这里暂停,直到下一次生成器被迭代self.flush()# 数据流发送完毕后,调用finish结束请求self.finish()def build_message(sekf, message: str, event="message"):"""构建消息:param message: 数据消息:param event: 事件,默认事件是“message”,可以根据自己的需求定制事件,对应前端的eventSource.addEventListener('message',()=>{}, false)中的message。:return:"""head = "event:" + event + "\n" + "data:"tail = "\n\n"return head + message + tail

main.py

import asyncioimport tornado
from tornado.httpserver import HTTPServer
from tornado.netutil import bind_socketsfrom route import make_app# 单进程
async def main():app = make_app()app.listen(8881)await asyncio.Event().wait()if __name__ == "__main__":asyncio.run(main())"""# 多进程,只有在多颗CPU上才能运行,不支持Windows
def main():sockets = bind_sockets(8888)tornado.process.fork_processes(0)async def post_fork_main():# 创建APPapp = make_app()# 创建服务server = HTTPServer(app)server.add_sockets(sockets)await asyncio.Event().wait()asyncio.run(post_fork_main())if __name__ == '__main__':main()"""

route.py

import tornadofrom socket_handler.message_handler import MessageWebSocket
from web_handler.form_handler import FormHandler
from web_handler.json_handler import JsonHandler
from web_handler.sse_handler import SseHandlerdef make_app():return tornado.web.Application([# 验证基础表单(r"/form", FormHandler),(r"/json", JsonHandler),(r"/sse", SseHandler),# Websocket请求(r"/msg", MessageWebSocket),])

3.2 前端代码

Vue3的SSE代码

<script setup lang="ts">
import { onBeforeUnmount} from 'vue'defineProps<{ msg: string }>()// 定义EventSource
let eventSource: any = null// 建立连接
function createSseConnect(dataId: string) {if (window.EventSource) {// 创建连接eventSource = new EventSource('http://127.0.0.1:8881/sse');console.log("test");// 接收消息eventSource.onmessage = (event: MessageEvent) => {console.log(event)console.log("onmessage:" + dataId + ": " + event.data)};// // 也可以使用addEventListener实现自定义事件和默认message事件// eventSource.addEventListener('message', (event: MessageEvent)=> {//     console.log("message" + dataId + ": " + event.data);// }, false);// 打开连接eventSource.onopen = (event: Event) => {console.log("onopen:" + dataId + ": " + event)};// 连接出错时eventSource.onerror = (event: Event) => {console.log(event)console.log("onerror :" + dataId + ": " + event)eventSource.close();};} else {console.log("浏览器不支持SSE")}
}// 组件销毁
onBeforeUnmount(() => {// 关闭EventSourceif(eventSource != null){eventSource.close()}
})</script><template><h1>{{ msg }}</h1><input type="button" value="发送消息" v-on:click="createSseConnect('1234')" /></template><style scoped>
.read-the-docs {color: #888;
}
</style>

Html5的WebSocket

<!DOCTYPE HTML>
<html><head><meta charset="utf-8"><script type="text/javascript">function WebSocketTest() {if ("WebSocket" in window) {// 构建WebSocketvar ws = new WebSocket("ws://localhost:8881/msg");ws.onopen = function () {// Web Socket 已连接上,使用 send() 方法发送数据ws.send("发送数据");alert("数据发送中...");};ws.onmessage = function (evt) {var received_msg = evt.data;console.log(received_msg)//   alert("数据已接收...");};ws.onclose = function () {// 关闭 websocketalert("连接已关闭...");};}else {// 浏览器不支持 WebSocketalert("您的浏览器不支持 WebSocket!");}}</script></head><body><div id="sse"><a href="javascript:WebSocketTest()">运行 WebSocket</a></div></body></html>

3.3 请求地址

# 表单请求
http://127.0.0.1:8888/form

在这里插入图片描述

# json请求
http://127.0.0.1:8888/json

在这里插入图片描述

# WebSocket请求
ws://127.0.0.1:8881/msg

在这里插入图片描述

# SSE请求
http://127.0.0.1:8881/sse

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/59591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

倍思获喜马拉雅年度最佳协作之星,打造移动数码品牌跨界新体验

近日,在“听见,共建,同行”——2024喜马拉雅有声之夜年度创作者大会暨峰爆榜颁奖典礼上,移动数码品牌Baseus倍思凭借其卓越的技术实力与创新的品牌理念,荣获“年度最佳协作之星”奖项。这一荣誉肯定了倍思在行业的深耕细作,也树立起品牌与喜马拉雅平台跨界合作、共同演绎音频生…

[单例模式]

[设计模式] 设计模式是软件工程中的一种常见做法, 它可以理解为"模板", 是针对一些常见的特定场景, 给出的一些比较好的固定的解决方案. 不同语言适用的设计模式是不一样的. 这里我们接下来要谈到的是java中典型的设计模式. 而且由于设计模式比较适合有一定编程经…

内部知识库:优化企业培训流程的关键驱动力

在当今快速变化的商业环境中&#xff0c;企业培训的重要性日益凸显。内部知识库作为整合、管理和分享企业内部学习资源的关键工具&#xff0c;正逐步成为优化企业培训流程的核心。以下将探讨内部知识库如何通过多种功能&#xff0c;助力企业提升培训效率、质量和员工满意度。 …

Ubuntu - 进入紧急模式,无法进入桌面

目录 一、问题 二、分析原因 三、解决 四、参考 一、问题 重新安装VMVare之后&#xff0c;将之前的虚拟机加载不进来 二、分析原因 查看系统错误日志 journalctl -xb | grep Failed mnt挂载找不到了 三、解决 查看系统错误日志 如果是磁盘错误&#xff0c;此时终端会有…

I.MX6U 裸机开发3. GPIO操作控制LED灯

I.MX6U 裸机开发3. GPIO操作控制LED灯 一、创建项目目录及源文件1. 新建目录2. 远程开发环境3. 创建源文件 二、代码编写1. 打开时钟2. 配置端口复用功能为GPIO3. 配置端口电气属性4. 设置GPIO方向&#xff08;GDIR寄存器&#xff09;5. 输出6. 死循环等待 三、编译程序1. 整体…

java ssm 公司内部员工管理系统 员工信息管理 企业员工 源码 jsp

一、项目简介 本项目是一套基于SSM的公司内部员工管理系统&#xff0c;主要针对计算机相关专业的和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本、软件工具等。 项目都经过严格调试&#xff0c;确保可以运行&#xff01; 二、技术实现 ​后端技术&am…

数据分析:宏基因组DESeq2差异分析筛选差异物种

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理:计算步骤:结果:加载R包准备画图主题数据链接导入数据Differential abundance (No BP vs 2BP TA)构建`countData`矩阵过滤低丰度物种构建DESeq数据对象DESeq2差异分析画图Di…

Spark的yarn集群环境搭建

一.为什么要搭建yarn集群 为什么要将Spark的程序运行在YARN上&#xff0c;不运行在自带的 Standalone集群上&#xff1f; 1、统一化资源管理 Standalone是Spark专用的资源管理集群&#xff0c;只能用于运行 Spark程序 YARN是功能的分布式资源管理平台&#xff0c;可以运行各种分…

51单片机教程(六)- LED流水灯

1 项目分析 基于点亮LED灯、LED灯闪烁&#xff0c;扩展到构成最简单、花样流水灯。 2 技术准备 1 流水灯硬件及原理图 流水灯是由多个LED灯组成的 2 C语言知识点 数组 数组声明&#xff1a;长度不可变 数据类型 数组名称[长度n] // 整数型默认为0&#xff0c;小数型默认…

PyQt5实战——翻译的实现,第一次爬取微软翻译经验总结(八)

个人博客&#xff1a;苏三有春的博客 系类往期文章&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; PyQt5实战——多脚本集合包&#xff0c;UI以及工程布局&#xff08;二&#xff09; PyQt5实战——多脚本集合包&#xff0c;程序…

前端好用的网站分享——CSS(持续更新中)

1.CSS Scan 点击进入CSS Scan CSS盒子阴影大全 2.渐变背景 点击进入color.oulu 3.CSS简化压缩 点击进入toptal 4.CSS可视化 点击进入CSS可视化 这个强推&#xff0c;话不多说&#xff0c;看图! 5.Marko 点击进入Marko 有很多按钮样式 6.getwaves 点击进入getwaves 生…

理解Web登录机制:会话管理与跟踪技术解析(三)-过滤器Filter

在Java Web应用中&#xff0c;Filter&#xff08;过滤器&#xff09;是实现登录校验的常见方式。通过Filter&#xff0c;我们能够在请求到达实际的业务逻辑之前&#xff0c;对其进行拦截和处理&#xff0c;从而完成身份校验、权限验证等操作。本文将深入探讨登录校验的实现方法…

FreeBSD将操作系统支持时间从5年缩短为4年 继续与AMD合作

FreeBSD 项目今天发布了 2024 年第三季度进度报告&#xff0c;概述了该开源 BSD 操作系统在上一季度的改进情况。FreeBSD 开发人员仍然非常忙碌&#xff0c;他们在 2024 年第三季度取得的一些成就包括&#xff1a; FreeBSD 发布团队决定将支持时限从五年缩短为四年。 AMD 与 F…

kafka如何获取 topic 主题的列表?

大家好&#xff0c;我是锋哥。今天分享关于【kafka如何获取 topic 主题的列表&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka如何获取 topic 主题的列表&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中&#xff0c;可以…

【网络-交换机】生成树协议、环路检测

路由优先级 路由优先级决定了在多种可达的路由类型中&#xff0c;哪种路由将被用来转发数据包。路由优先级值越低&#xff0c;对应路由的优先级越高&#xff0c;优先级值255表示对应的路由不可达。一般情况下&#xff0c;静态路由的优先级为1&#xff0c;OSPF路由优先级为110&a…

基于Spring Boot的在线装修管理系统的设计与实现,LW+源码+讲解

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#…

【数字图像处理】图像旋转中三种常见插值方法的效果比较:最近邻插值、双线性插值和双三次插值

引言 插值是一种数学方法&#xff0c;用于在已知的数据点之间估计新的数据点。在图像处理中&#xff0c;插值通常用于图像缩放、旋转和其他形态变换。 原始图像 最近邻插值&#xff08;Nearest-neighbor interpolation&#xff09; 这是最简单的插值方法&#xff0c;也是计算…

“方块兽神仙猿点石成金”游戏搭建开发

“方块兽神仙猿点石成金”是一款结合了策略和运气的休闲游戏。玩家需在规定时间内向不同的山头投入矿石&#xff0c;等待神仙猿降临并随机选择一座山进行“点石成金”。根据神仙猿的选择&#xff0c;玩家将获得不同的奖励。 游戏核心机制 矿石投入&#xff1a;玩家在游戏开始…

C/C++每日一练:实现选择排序

选择排序 选择排序是一种简单直观的排序算法&#xff0c;时间复杂度为&#xff0c;其中 n 是数组长度&#xff0c;不适合大数据集的排序&#xff0c;适合于元素较少且对性能要求不高的场景。 选择排序的基本思想是&#xff1a;每次从未排序部分选择最小的元素&#xff0c;将其放…

Java8新特性/java

1.lambda表达式 区别于js的箭头函数&#xff0c;python、cpp的lambda表达式&#xff0c;java8的lambda是一个匿名函数&#xff0c;java8运行把函数作为参数传递进方法中。 语法格式 (parameters) -> expression 或 (parameters...) ->{ statements; }实战 替代匿名内部类…