文章目录
1、web应用
1.1、定义
Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览器,强调:S端由server和application两大部分构成,如图所示:
1.2、web应用的优点
- 不需要客户端
- 更新直接在服务端更新,客户端感知不到
- 跨平台性好
1.3、web应用的缺点
- 强调浏览器的适用性
- 用户的数据都保存在软件厂商那边
1.4、bs、cs架构
bs:浏览器—服务端(本质还是cs)
cs:客户端—服务端
1.5、基于socket写一个web应用
1.5.1、main.py
import socket
def server_run():
soc = socket.socket()
soc.bind(('127.0.0.1', 8008))
soc.listen(5)
while True:
conn, addr = soc.accept()
recv_data = conn.recv(1024)
print(recv_data)
# 1 直接在send里写,发送给客户端
# conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>hello web</h1><img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg"></img>')
#2 打开一个html文件,发送给客户端
# with open('index.html','r',encoding='utf-8') as f:
# data=f.read()
# conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8'))
# 3 动态网页,字符串替换
import time
now=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(now)
with open('index.html','r',encoding='utf-8') as f:
data=f.read()
data=data.replace('@@@',now)
conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8'))
conn.close()
if __name__ == '__main__':
server_run()
1.5.2、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>@@@</h2>
<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1601099256336&di=f664b8fa21a9d3e642112a1e1cc8d885&imgtype=0&src=http%3A%2F%2Fa3.att.hudong.com%2F14%2F75%2F01300000164186121366756803686.jpg" alt="">
</body>
</html>
2、web框架
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的,web框架就是在以上几十行代码基础上扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率
2.1、基于wsgiref写一个web框架
1、socket自己写,借助于一个模块,已经实现了socket
2、wsgiref:django默认使用的
3、在web框架上继续开发
- 以后路径都去urls.py中写
- 路径匹配以后执行的函数,都放在views.py
- 数据库相关操作,在models.py中
wsgiref简单使用
from wsgiref.simple_server import make_server
def server(environ, start_response): # 必须传两个参数
# environ是字典,http请求拆成字典,请求方式,请求地址,请求头...
# start_response: 响应对象,响应状态码,响应头放到里面
start_response('200 OK', [('Content-Type', 'text/html')])
if environ.get('PATH_INFO') == '/index': # 请求地址
data = '我是index页面'.encode('utf-8')
elif environ.get('PATH_INFO') == '/login':
data = '我是login页面'.encode('utf-8')
else:
data = b'<h1>Hello, web!</h1>'
return [data]
if __name__ == '__main__':
# app是可调用对象,可以加括号执行的(函数内存地址)
myserver = make_server('127.0.0.1', 8081, server) # 只要客户端发送一次请求,就会调用server()
myserver.serve_forever() # 服务就起来了,相当于之前写的socket一直监听8081端口
2.2、基于wsgiref自定义web框架
2.2.1、models.py
'''
链接数据库返回字典格式:
cursor=pymysql.cursors.DictCursor
'''
import pymysql
# 连接数据库
conn = pymysql.connect(host='127.0.0.1',port= 3307,user = 'root',passwd='root',db='web') # db: 库名
# 创建游标
cur = conn.cursor()
sql='''
create table userinfo(
id INT PRIMARY KEY ,
name VARCHAR(32) ,
password VARCHAR(32)
)
'''
cur.execute(sql)
# 提交
conn.commit()
# 关闭指针对象
cur.close()
# 关闭连接对象
conn.close()
2.2.2、myserver.py
from wsgiref.simple_server import make_server
from urls import url_patters
def mya(environ, start_response):
# print(environ)
start_response('200 OK', [('Content-Type', 'text/html')])
func = None
for item in url_patters:
if item[0] == environ.get('PATH_INFO'):
func = item[1]
break
if func:
data = func(environ)
return [data]
else:
return [b'404']
if __name__ == '__main__':
myserver = make_server('', 8011, mya)
print('监听8010')
myserver.serve_forever()
2.2.3、urls.py
from views import *
url_patters = [
('/login', login),
('/index', index),
('/time', time),
]
2.2.4、views.py
def index(environ):
with open('templates/index.html', 'rb') as f:
data = f.read()
return data
def time(environ):
import datetime
now=datetime.datetime.now().strftime('%y-%m-%d %X')
print(now)
return now.encode('utf-8')
from urllib.parse import parse_qs
import pymysql
def login(request):
if request.get("REQUEST_METHOD") == "POST":
try:
request_body_size = int(request.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
request_body = request['wsgi.input'].read(request_body_size)
data = parse_qs(request_body)
user = data.get(b"user")[0].decode("utf8")
pwd = data.get(b"pwd")[0].decode("utf8")
# 连接数据库
conn = pymysql.connect(host='127.0.0.1', port=3307, user='root', passwd='root', db='web') # db: 库名
# 创建游标
cur = conn.cursor()
SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'" % (user, pwd)
cur.execute(SQL)
if cur.fetchone():
f = open("templates/backend.html", "rb")
data = f.read()
data = data.decode("utf8")
return data.encode("utf8")
else:
print("OK456")
return b"user or pwd is wrong"
else:
f = open("templates/login.html", "rb")
data = f.read()
f.close()
return data
2.2.5、tempaltes下backend.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
登录成功
</body>
</html>
2.2.6、tempaltes下index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
index
</body>
</html>
2.2.7、tempaltes下login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>登录页面</h4>
<form action="http://127.0.0.1:8011/login" method="post">
用户名 <input type="text" name="user">
密码 <input type="text" name="pwd">
<input type="submit">
</form>
</body>
</html>
3、其它socket服务端
'cgi': CGIServer,
'flup': FlupFCGIServer,
'wsgiref': WSGIRefServer,
'waitress': WaitressServer,
'cherrypy': CherryPyServer,
'paste': PasteServer,
'fapws3': FapwsServer,
'tornado': TornadoServer,
'gae': AppEngineServer,
'twisted': TwistedServer,
'diesel': DieselServer,
'meinheld': MeinheldServer,
'gunicorn': GunicornServer,
'eventlet': EventletServer,
'gevent': GeventServer,
'geventSocketIO':GeventSocketIOServer,
'rocket': RocketServer,
'bjoern' : BjoernServer,
'auto': AutoServer,
都遵循一个协议wsgi(Web Server Gateway Interface web服务网关接口)