20-2 树莓派搭建服务器 Tornado Web服务器
Drive.google.com/drive/folders/1ahbeoEHkjxoo4NV1wReOmpoRWbl448z-
1.Tornado简介
Tornado一款使用 Python 编写的,相对简单的 非阻塞式 Web 服务器,它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。
官方网站:http://www.tornadoweb.cn
官方文档:http://www.tornadoweb.cn/documentation
整个文档就一个网页,把http服务器常用的功能都讲述了一遍,如果有编程基础,应该很快就能上手。
2.Tornado安装
方式1:pip 安装:
sudo pip install tornado
方式2:源代码安装:
wget https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
tar xvzf tornado-4.3.tar.gz
cd tornado-4.3
python setup.py build
sudo python setup.py install
二、基本原理
借用Tornado官方的Hello World例子:
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") application = tornado.web.Application([
(r"/", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
大致的思路是:通过Tornado开启http端口侦听,预设好路由规则,当有请求符合路由规则时,调用对应的Handler进行处理,这也是大部分Web服务器的处理方式。支持get和post请求。
扩展一下,利用Tornado搭建一个http服务器,上面放一个网页,网页端传入需要控制的GPIO针脚编号和状态,服务器端接收到传入的参数,做相应的处理,即可实现控制GPIO针脚电平的输出了。
三、实现步骤
1.前端html页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>树莓派Web控制中心</title>
<script src="static/js/jquery-3.2.1.min.js" type="text/javascript"></script>
<script src="static/js/bootstrap.min.js" type="text/javascript"></script>
<link href="static/css/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="static/css/font-awesome-4.7.0/css/font-awesome.min.css" rel="stylesheet"
type="text/css" />
<style type="text/css">
.page-header { margin: 20px 0; border-bottom: 1px solid #eee; padding-bottom: 0; text-align: center; }
.btn-item { text-align: center; }
i { margin-right: 3px; display: inline-block; }
h1 { text-align: center; }
.tip { font-weight: bold; color: black; }
.lead { font-size: small; }
.gpio-item { text-align: center; }
.btn-gnd, .btn-gpio { padding: 10px 5px; margin-bottom: 5px; width: 100%; font-size: small; }
.gpio .row { margin-top: 5px; }
</style>
</head>
<body>
<div class="container">
<div class="page-header">
<h3>
树莓派Web控制中心</h3>
<p class="lead">
用于控制连接到树莓派的各种传感器
</p>
</div>
<div class="panel panel-default">
<div class="panel-heading">
设备</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-3 btn-item">
</div>
<div class="col-xs-3 btn-item">
<a class="btn btn-danger btn-trigger"><i class="fa fa-power-off"></i>关机</a>
</div>
<div class="col-xs-3 btn-item">
<a class="btn btn-primary btn-trigger"><i class="fa fa-refresh"></i>重启</a>
</div>
<div class="col-xs-3 btn-item">
</div>
<script type="text/javascript">
var url = "/";
$(function () {
$(".btn-trigger").click(function () {
var text = $(this).text().replace(/ /g, "").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "");
var cmd = "";
switch (text) {
case "关机":
cmd = "sudo shutdown -h now";
break;
case "重启":
cmd = "sudo reboot";
break;
}
if (confirm("确定要执行该命令吗?")) {
$.ajax({
type: "POST",
url: url,
data: {
action: "run-shell-cmd",
cmd: cmd
},
success: function (result) {
//$(".tip").html(result);
}
});
}
});
});
</script>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
GPIO (蓝色->低电平,红色->高电平)</div>
<div class="panel-body gpio">
<div class="row">
<div class="col-xs-6 gpio-item">
左侧
</div>
<div class="col-xs-6 gpio-item">
右侧
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (9) 左05</button>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (6) 右03</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="17">17 (11) 左06</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="18">18 (12) 右06</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="27">27 (13) 左07</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (14) 右07</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="22">22 (15) 左08</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="23">23 (16) 右08</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (25) 左13</button>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="24">24 (18) 右09</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="5">05 (29) 左15</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (20) 右10</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="6">06 (31) 左16</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="25">25 (22) 右11</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="13">13 (33) 左17</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (30) 右15</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="19">19 (35) 左18</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="12">12 (32) 右16</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="26">26 (37) 左19</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (34) 右17</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="20">20 (37) 右19</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="16">16 (36) 右18</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (39) 右20</button>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio" pin="21">21 (40) 右20</a>
</div>
</div>
<script type="text/javascript">
$(function () {
$(".btn-gpio").click(function () {
var gpio = $(this).attr("pin");
if ($(this).hasClass("btn-danger")) {
$(this).removeClass("btn-danger").addClass("btn-primary");
} else {
$(this).removeClass("btn-primary").addClass("btn-danger");
}
var status = $(this).hasClass("btn-danger") ? 1 : 0;
$.ajax({
type: "POST",
url: url,
data: {
action: "set-gpio-pin",
pin: gpio,
status: status
},
success: function (result) {
//$(".tip").html(result);
}
}); });
})
</script>
</div>
</div>
</div>
</body>
</html>
2.Python脚本
#coding: utf8
import sys
import RPi.GPIO as GPIO
import time
import os
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options
from tornado.options import define,options #初始化
def init():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) #设置GPIO针脚电平输出
def SetPinStatus(pin,status):
GPIO.cleanup(int(pin))
GPIO.setup(int(pin),GPIO.OUT)
if(int(status)==0):
GPIO.output(int(pin),GPIO.LOW)
else:
GPIO.output(int(pin),GPIO.HIGH) #路由处理
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def post(self):
init()
action=self.get_argument('action')
#设置GPIO针脚电平输出
if(action=="set-gpio-pin"):
pin = self.get_argument('pin')
status = self.get_argument('status')
SetPinStatus(pin,status)
self.write("true")
#执行shell脚本,如:关机,重启
elif(action=="run-shell-cmd"):
cmd = self.get_argument('cmd')
os.system(cmd) if __name__ == '__main__':
#控制台输出响应结果,正式环境可以不开启
#tornado.options.parse_command_line()
settings={
"static_path":os.path.join(os.path.dirname(__file__),"static")
}
app = tornado.web.Application(
handlers=[
(r"/",IndexHandler),
(r"(apple-touch-icon\.png)",tornado.web.StaticFileHandler,dict(path=settings['static_path']))
],**settings) http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(8020)
tornado.ioloop.IOLoop.instance().start()
GPIO.cleanup()
3.目录结构
4.部署调试
在终端输入:python /var/www/html/pi/gpio/gpio.py (路径为我树莓派中文件路径,实际路径以你自己的环境为准。)
如果终端没报错,此时打开浏览器,输入地址:http://localhost:8020 即可访问到页面,8020是python脚本中侦听的端口,你可以自行设置。
5.运行结果
6.源码下载
http://download.csdn.net/download/a497785609/9990088
20-2 树莓派搭建服务器 Tornado Web服务器的更多相关文章
- linux系统下搭建自己的web服务器
之前在windows 2008 server上搭建了一个用于测试的web服务器,但是在打开网站的时候特别的慢,尤其是图片的加载都会失败,当时以为是路径的问题,但是在服务器上自己打开都特别慢,自己实在找 ...
- [阿里云部署] Ubuntu+Flask+Nginx+uWSGI+Mysql搭建阿里云Web服务器
部署地址:123.56.7.181 Ubuntu+Flask+Nginx+uWSGI+Mysql搭建阿里云Web服务器 这个标题就比之前的"ECS服务器配置Web环境的全过程及参考资料&qu ...
- 基于python2【重要】怎么自行搭建简单的web服务器
基本流程:1.需要的支持 1)python本身有SimpleHTTPServer 2)ForkStaticServer.py支持,该文件放在python7目录下 3)将希望共享 ...
- nginx搭建前端项目web服务器以及利用反向代理调试远程后台接口
前端同学用nginx搭建自己的web服务器,后台程序专门部署在一台服务器上(我们之前公司就有三套环境,开发/测试/生产),这样做的好处是 1.前端代码基本都是静态文件,重启一次很快,也就几秒钟时间. ...
- 使用 Nginx 搭建静态资源 web 服务器
在搭建网站的时候,往往会加载很多的图片,如果都从 Tomcat 服务器来获取静态资源,这样会增加服务器的负载,使得服务器运行 速度非常慢,这时可以使用 Nginx 服务器来加载这些静态资源,这样就可以 ...
- 用go-module作为包管理器搭建go的web服务器
本篇博客主要介绍了如何从零开始,使用Go Module作为依赖管理,基于Gin来一步一步搭建Go的Web服务器.并使用Endless来使服务器平滑重启,使用Swagger来自动生成Api文档. 源码在 ...
- 22-1 web传输视频 Opencv+usb摄像头 树莓派+Flask实现视频流媒体WEB服务器
第一篇 讲解原理 https://blog.miguelgrinberg.com/post/video-streaming-with-flask 第二篇 加入多线程可以直接用 https://gith ...
- 游戏服务器和Web服务器的区别
用Go语言写游戏服务器也有一个多月了,也能够明显的感受到两者的区别.这篇文章就是想具体的聊聊其中的区别.当然,在了解区别之间,我们先简单的了解一下Go语言本身. 1. Go语言的特点 Go语言跟其他的 ...
- 树莓派做下载机+Web服务器(Aria2下载+yaaw做UI+nginx)
今天收到了小派,UK产的绿板子,还配了个透明盒子,装在里面闪亮亮的很好看,而且只有卡片大小,寻思着用它做什么好呢?想来想去,看到人家拿小派作家庭媒体中心,还有人拿它当下载机,于是就萌生了一个家庭媒体中 ...
随机推荐
- 『正睿OI 2019SC Day5』
网络流 网络流的定义 一个流网络\(G=(V,E)\)为一张满足以下条件的有向图: 每一条边有一个非负容量,即对于任意\(E\)中的\((u,v)\) , 有\(c(u,v)\geq0\). 如果\( ...
- 『正睿OI 2019SC Day3』
容斥原理 容斥原理指的是一种排重,补漏的计算思想,形式化的来说,我们有如下公式: \[\left | \bigcup_{i=1}^nS_i \right |=\sum_{i}|S_i|-\sum_{i ...
- 运行带有Activiti modeler时,出现这样的报错: java.rmi.AccessException: Cannot modify this registry
最近在做整合Activiti Modeler工作流在线设计器的工作,运行IDEA时,出现了这样一个错误信息: 原因及解决办法: Activiti默认打开了jmx功能,默认端口为1099,idea中 ...
- 整理:WPF中XmlDataProvider的用法总结
原文:整理:WPF中XmlDataProvider的用法总结 一.目的:了解XmlDataProvider中绑定数据的方法 二.绑定方式主要有三种: 1.Xaml资源中内置: <!--XPath ...
- VS2019+EF6连接Mysql
开发环境:Win10 + VS2019Mysql服务器版本:8.0.16 一.下载并安装插件(必备) MySQL-Connector-net-6.9.12 链接https://cdn.mysql.c ...
- 记录一次使用NPOI遇到的问题
在.net 下一般使用NPOI操作Excel相信大家都不陌生,但是本人在操作过程中遇到一个比较奇怪的问题,特写此博客记录与大家分享. 例子是使用Winform,点击按钮时弹出打开文件对话框,然后选择文 ...
- 解决WPF下popup不随着window一起移动的问题
/// <summary> /// Popup帮助类,解决Popup设置StayOpen="True"时,移动窗体或者改变窗体大小时,Popup不随窗体移动的问题 // ...
- Linux下mongoDB下载与安装
原文连接:(http://www.studyshare.cn/blog/details/1168/0)一.下载 官网下载:点击下载 选择合适的版本 百度网盘下载:点击下载 提取码:rm12 此处提供 ...
- java.net.URLEncoder对中文的编码和解码
// java.net.URLEncoder对中文的编码和解码String str = URLEncoder.encode("测试字符串", "utf-8"); ...
- 修改docker容器参数
创建容器时没有添加参数 --restart=always ,导致的后果是:当 Docker 重启时,容器未能自动启动. docker container update --restart=alway ...