WSGI协议---02
为什么要说WSGI
自己写的服务器是支持不了高并发的,因此一般是用现成的比较优秀的服务器,一般有apache,nginx等等,但是用别人写的服务器是可能像自己写的一样直接import的,可能我们拿到的就是汇编或者二进制代码,那么怎么让别人的服务器支持自己写的前端页面呢,只要我们遵循WSGI协议就可以。
WSGI协议流程
浏览器请求http协议动态资源,web服务器调用一个属性,一般来说这个属性是application(),我们在自己的应用程序框架里面也要协商application函数,里面两个参数,一个字典一个函数指针。然后应用程序框架里面通过引用调用的web服务器的方法,设置返回的状态和头信息(这里的状态其实就是404或者200 OK)。web服务器调用返回,此时web服务器保存了刚刚设置的信息。应用程序框架生成动态页面的body信息。把生成的信息返回给web服务器调用。简而言之,wsgi是将python服务器程序连接到web服务器的通用协议uwsgi是独立的实现了wsgi协议的服务器。
自写的服务器,解耦合
关键代码
body=test.application(file_name) #接耦合
server完整代码
import socket
import re
import multiprocessing
import time
import test
class WSGIserver(object):
def __init__(self):
# 1. 创建套接字
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2. 绑定
self.tcp_server_socket.bind(("172.16.70.64", 7890))
# 3. 变为监听套接字
self.tcp_server_socket.listen(128)
def service_client(self, new_socket):
"""为这个客户端返回数据"""
# 1. 接收浏览器发送过来的请求 ,即http请求
# GET / HTTP/1.1
# .....
request = new_socket.recv(1024).decode("utf-8")
# print(">>>"*50)
# print(request)
request_lines = request.splitlines()
print("")
print(">" * 20)
print(request_lines)
# GET /index.html HTTP/1.1
# get post put del
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
if ret:
file_name = ret.group(1)
# print("*"*50, file_name)
if file_name == "/":
file_name = "/index.html"
# 2. 返回http格式的数据,给浏览器
# 如果请求的资源不是.py结尾的就认为是静态资源
if not file_name.endswith(".py"):
try:
f = open("../html" + file_name, "rb")
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()
# 2.1 准备发送给浏览器的数据---header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 准备发送给浏览器的数据---boy
# response += "hahahhah"
# 将response header发送给浏览器
new_socket.send(response.encode("utf-8"))
# 将response body发送给浏览器
new_socket.send(html_content)
else:
# 如果是已.py结尾那么就认为是动态请求
header="HTTP/1.1 200 OK\r\n"
header+="\r\n"
body=test.application(file_name) #接耦合
#body=test.login()
response=header+body
new_socket.send(response.encode("utf-8"))
# 关闭套接
new_socket.close()
def runforever(self):
"""用来完成整体的控制"""
while True:
# 4. 等待新客户端的链接
new_socket, client_addr = self.tcp_server_socket.accept()
# 开一个进程
p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
p.start()
new_socket.close()
# # 5. 为这个客户端服务
# service_client(new_socket)
# 关闭监听套接字
tcp_server_socket.close()
def main():
"""
控制整体,创建一个web服务器对象,然后调用这个对象的run方法
:return:None
"""
wsgi_server = WSGIserver()
wsgi_server.runforever()
if __name__ == "__main__":
main()
test应用程序框架完整代码
import time
def login():
return "welcome to our website ----time is %s "%time.time()
def register():
return "登录"
def profile():
return "个人主页"
def application(file_name):
if file_name=="/log_in.py":
login()
elif file_name=="/register.py":
register()
elif file_name=="/profile.py":
profile()
else:
return "没有发现你的主页"
** 完整程序已上传git,拉至最后查看地址 **
自写服务器实现WSGI协议支持
server文件改动
else:
env=dict()#空字典
body=test.application(env,self.set_response_header) #接耦合
# 如果是已.py结尾那么就认为是动态请求
header = "HTTP/1.1 200 OK %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,status ,headers):
self.status=status
self.headers=headers
test应用程序框架改动
def application(environ,start_response):
start_response("200 OK",[('Content-Type','text/html')])
return 'Hello World!'
** 完整程序已上传git,拉至最后查看地址 **
encode方式
test文件
def application(environ,start_response):
start_response("200 OK",[('Content-Type','text/html;charset=utf-8')])
return 'Hello World!我爱你中国'
application函数的字典参数使用
用字典去存file_name,test里面读取字典,显示相应信息
server文件改动
else:
env=dict()#空字典
env['PATH_INFO']=file_name
body=test.application(env,self.set_response_header) #接耦合
# 如果是已.py结尾那么就认为是动态请求
header = "HTTP/1.1 200 OK %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"))
test文件改动
def index():
return "主页"
def login():
return "登录"
def application(env,start_response):
start_response("200 OK",[('Content-Type','text/html;charset=utf-8'),('server','my_web')])
file_name=env['PATH_INFO']
if file_name=="/index.py":
return index()
elif file_name == "/login.py":
return login()
else:
return 'Hello World!我爱你中国'
** 完整程序已上传git,拉至最后查看地址 **
author:[email protected]
github: https://github.com/zhangyuespec/mini_web