目的:搭建最简单的服务器框架(访问本地静态和动态资源)
一、大致思路:
1、创建监听套接字
2、绑定本地信息(IP和port)
3、使用listen改变监听状态
4、等待客户端(浏览器)的链接,并创建为客户端服务的服务套接字(使用多进程调用服务方法为客户端服务)
5、服务方法:获取客户端发送的数据>>>使用正则表达式匹配客户端发送的信息,获得服务端需要的信息
>>>访问静态网页,直接本地匹配资源地址,读取并发送给客户端(浏览器)
>>>访问动态资源,调用框架的application方法,获取框架返回的数据,组装成响应数据,发送给客户端(浏览器)
上代码:Wsgi_Server.py
from socket import *
import re,multiprocessing,time
import mini_frame
class WSGIServer(object):
def __init__(self):
# 1、创建监听套接字
self.server_socket = socket(AF_INET, SOCK_STREAM)
self.server_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
# self.server_socket.setblocking(False)
# 2、绑定本地IP和port信息,本地信息使用元组格式
self.server_socket.bind(('', 8080))
# 3、使用listen改变监听状态,设置监听容量
self.server_socket.listen(128)
def client_sever(self,new_socket):
# 5、获取客户端发送的信息,并设置接收数据字节大小
request = new_socket.recv(1024).decode('utf-8')
# 6、使用正则表达式匹配客户端发送的信息,获得服务端需要的信息,本地匹配资源地址
g = re.match(r'[^/]*/+([^ ]*)\s+', request)
if g:
file_name = g.group(1)
# 7、根据匹配结果,在本地进行操作
# 打开本地资源,读取本地数据作为响应体
if not file_name.endswith('.py'):
try: # 执行代码
with open(file_name, 'rb') as f:
response_body = f.read()
except: # 发生异常时执行
response_body = '<h1>hello world! not found</h1>'.encode('utf-8')
finally: # 不管有没有异常时,都会执行的代码
response_header = 'HTTP/1.1\r\n'
response_header += '\r\n'
print(file_name)
# 组装本地数据
response = response_header.encode('utf-8') + response_body
# 8、发送匹配后的本地资源给客户端
new_socket.send(response)
# 9、关闭客户端套接字,结束服务,等待下一个客户端链接。
new_socket.close()
else:
# 调用框架的application方法,传递字典和类方法,支持wsgi协议
env=dict()
env['path_info'] = file_name
response_body = mini_frame.application(env,self.start_response)
# 组装响应头,注意,每行数据后面必须加 \r\n
response_header = 'HTTP/1.1 {} \r\n'.format(self.status)
for i in self.hearders:
response_header += '{}:{}\r\n'.format(i[0],i[1])
response_header += '\r\n'
response =response_header + response_body
new_socket.send(response.encode('utf-8'))
# 9、关闭客户端套接字,结束服务,等待下一个客户端链接。
new_socket.close()
def start_response(self,status,hearders):
# 保存框架返回的状态码和响应头,为类属性,方便后续调用
self.status = status
self.hearders = hearders
def run_forever(self):
while True:
# 4、接收服务端链接,创建为客户端服务的客户端套接字
new_socket, client_addr = self.server_socket.accept()
# 创建进程为客户端服务
p=multiprocessing.Process(target=self.client_sever,args=(new_socket,))
p.start()
# 关闭客户套接字
new_socket.close()
def main():
'''控制整体,创建一个web服务器对象,然后调用一个方法来执行'''
w=WSGIServer()
w.run_forever()
if __name__ == '__main__':
main()
mini_frame.py
import time
def login():
return '这是登录页,当前时间:{}'.format(time.ctime())
def index():
return '这是主页,当前时间:{}'.format(time.ctime())
def application(env,start_response):
# 调用传递过来的方法,返回响应状态码和头部信息
start_response('200 OK',[('Content-Type','text/html;charset=UTF-8')])
if env['path_info'] == 'login.py':
return login()
elif env['path_info'] == 'index.py':
return index()
else:
return 'hello world!冬天来了的body'