首先说下这个程序的整体设计思想
程序的分为三大块
Web服务器,web框架,还有模板
Web服务器是由socket模块做的
Web框架和web服务器之间的数据传送是基于WSGI协议
由于web服务器要同时能接受多个用户的访问 ,所以就用了进程
不知道大家独一WSGI协议了解不了解这里简单说下
Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。
他的工作流程是这样的
就是说当一个浏览器访问这个网站时,首先给这个网站服务器发送一个请求,然后服务器接收到这个请求后,服务器调用application这个函数,这个函数接受两个参数,一个是字典,一个是一个服务器中的一个start_response函数的引用,env字典中装的是浏览器发过来的路径,这个函数中有两个参数需要传递,一个状态码,一个是内容类型,当服务器调用application这个函数时,就会运行web框架中的application函数 ,然后web框架中的application根据env字典中的路径找到相应的模板,start_response中这个函数需要接受两个参数,此时传递给他,然后将模板中的内容和start_response接受到的两个参数传递给服务器,然后服务器在发送给浏览器
```python、
# Web服务器
import socket
import re
import multiprocessing
import time, sys
# from danamic import mini_frame
class WSGIServer(object):
def __init__(self, port, app, conf_info):
# 创建套接字
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定
self.tcp_server_socket.bind(("", port))
# 变为监听套接字
self.tcp_server_socket.listen(128)
self.application = app
self.conf_info = conf_info
def service_client(self, new_socket):
# 接受浏览器发送过来的请求
request = new_socket.recv(1024).decode("utf-8")
request_lines = request.splitlines()
print("")
print(">"*20)
print(request_lines)
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
print(ret, "+"*20)
if ret:
file_name = ret.group(1)
if file_name == "/":
file_name = "/index.html"
# 返回HTTP格式的数据,给浏览器
if not file_name.endswith(".py"):
print(file_name, "+"*50)
try:
f = open(self.conf_info + file_name, "rb")
print(f, "+"*50)
except:
response = "HTTP/1.1 404 NOT FOUND \r\n"
response += "\r\n"
response += "------file not found ------"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 返回HTTP格式的数据给浏览器
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 将response.header 发送给浏览器
new_socket.send(response.encode("utf-8"))
new_socket.send(html_content)
else:
env = dict()
env["PATH_INFO"] = file_name
body = self.application(env, self.set_response_header)
header = "HTTP/1.1 %s\r\n" % self.status
for temp in self.headers:
header += "%s:%s\r\n" % (temp[0], temp[1])
header += "\r\n"
response = header + body
new_socket.send(response.encode("utf-8"))
new_socket.close()
def set_response_header(self, starts, headers):
self.status = starts
self.headers = [("Server","mini_web v8.8")]
self.headers += headers
def server_run(self):
while True:
# 等待新的客户端连接
new_socket, client_addr = self.tcp_server_socket.accept()
# 为这个客户端服务
p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
p.start()
new_socket.close()
self.tcp_server_socket.close()
def main():
if len(sys.argv) == 3:
try:
port = int(sys.argv[1])
frame_app_name = sys.argv[2]
except Exception as ret:
print("端口输入错误")
return
else:
print("请以一下方式运行")
print("python web_server.py 7890 mini_frame:application")
return
ret = re.match(r"([^:]+):(.*)", frame_app_name)
if ret:
frame_name = ret.group(1)
app_name = ret.group(2)
else:
print("请以一下方式运行")
print("python web_server.py 7890 mini_frame:application")
return
with open("./web_conf.conf") as f:
conf_info = eval(f.read())
sys.path.append(conf_info['danamic_path'])
frame = __import__(frame_name)
app = getattr(frame, app_name)
wsgi_server = WSGIServer(port, app, conf_info["static_path"])
wsgi_server.server_run()
if __name__ == '__main__':
main()
URL_FUNC_DICT = dict()
def route(url):
def set_func(func):
URL_FUNC_DICT[url] = func
def call_func(*args, **kwargs):
return func(*args, **kwargs)
return call_func
return set_func
@route("/index.py")
def index():
with open("./template/index.html", encoding="utf-8") as f:
content = f.read()
return content
@route("/login.py")
def login():
return "这个是登录页"
# URL_FUNC_DICT = {
# "/index.py": index,
# "/login.py": login,
# }
def application(env, start_response):
start_response("200 OK", [("Content-Type", "text/html;charset=utf-8")])
file_name = env["PATH_INFO"]
# if file_name == "/index.py":
# return index()
# elif file_name == "/login.py":
# return login()
# else:
# return "Hello World 我爱你"
try:
# func = URL_FUNC_DICT[file_name]
# return func()
return URL_FUNC_DICT[file_name]()
except Exception as ret:
print("产生异常%s" % str(ret))