1.简单实现web服务框架
使用协程实现并发,也可换成进程
准备文件——index.html (见附)
说明:一下代码可直接复制粘贴
Web_server.py
from gevent import monkey
monkey.patch_all()
import socket
import gevent
import re
import application
class WebServer(object):
"""服务器类"""
def __init__(self):
"""
对象初始化
"""
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口重用
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
self.tcp_server_socket.bind(("", 8080))
# 监听网络,套接字由主动变为被动,最大监听数为128
self.tcp_server_socket.listen(128)
def run(self):
# 接收客户端的连接
while True:
new_socket, addr = self.tcp_server_socket.accept()
gevent.spawn(self.deal_request, new_socket)
def deal_request(self, new_socket):
# 接收客户请求数据
request_data = new_socket.recv(1024)
# 判断数据是否存在
if not request_data:
new_socket.close()
return
request_data_str = request_data.decode()
# 获取请求行
request_list = request_data_str.split("\r\n")
request_line = request_list[0]
# 获取请求路径
result = re.search(r"\s(.*)\s", request_line)
path = result.group(1)
# 判断路径是否存在
if not path:
new_socket.close()
return
if path == "/":
path = "/index.html"
if not path.endswith(".py"): # 静态资源(假设不是以py结尾的都是静态资源)
try:
with open(path, "rb") as file:
response_content = file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server:python-Web 1.1 \r\n" + "\r\n"
response_content = "ERROR!!! %s" % e
response_content = response_content.encode()
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Server:python-Web 1.1\r\n" + "\r\n"
# # 拼接响应协议
# response_data = (response_line + response_header).encode() + response_content
# # 发送响应协议
# new_socket.send(response_data)
# # 关闭套接字
# new_socket.close()
else: # 动态资源
env = {'url': path}
# 符合wsgi协议的端口 env:字典 传入回调函数引用地址,返回状态吗码和响应头【元组】
response_content = application.app(env, self.start_response)
response_line = "HTTP/1.1 %s\r\n" % self.statue
response_header = ""
# 遍历元组
for i in self.headers:
response_header += "%s:%s\r\n" % (i[0], i[1])
response_header += "\r\n"
# 拼接响应协议
response_data = (response_line + response_header).encode() + response_content
# 发送响应数据
new_socket.send(response_data)
# 关闭套接字
new_socket.close()
# 定义回调函数
def start_response(self, statue, headers):
self.statue = statue
self.headers = headers
def __del__(self):
self.tcp_server_socket.close()
if __name__ == '__main__':
server = WebServer()
server.run()
# 定义路由列表,其实定义的是个字典,也可利用列表套元组的方式,个人偏向字典
route_list = dict()
# 设计装饰器
def route(date):
def func1(func):
# 添加键值对——> 地址:函数
route_list[date] = func
def func2():
func()
return func2
return func1
@route("/index.py")
def index():
try:
# 假设调用的是index.py文件
with open("/index.html", 'rb') as file:
response_content = file.read()
except Exception as e:
return ("%s" % e).encode()
else:
return response_content
def app(env, start_response):
path = env['url']
statue = "200 OK"
headers = [('Connection', 'keep-Alive'), ('Server', 'python-web 1.1')]
# 调用回调函数
start_response(statue, headers)
try:
return route_list[path]() # 自动调用路径对应的函数
except Exception as e:
return "%s" % e
附: index.html 内容, 可直接复制创建文件
<!DOCTYPE html>
<html>
<head>
<title>Welcome </title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to Python Web Server!</h1>
<p>If you see this page, the python web server is successfully installed and
working.</p>
<p><em>Congratulation to you!.</em></p>
</body>
</html>