import socket
import select
class HttpRequest(object):
"""
用户封装用户请求信息
"""
def __init__(self, content):
"""
:param content: 请求头、请求体
"""
self.content = content
self.header_bytes = bytes()
self.header_dict = {}
self.body_bytes = bytes()
self.method = ""
self.url = ""
self.protocol = ""
self.initialize()
self.initialize_headers()
def initialize(self):
temp = self.content.split(b'\r\n\r\n', 1) #分割请求体、头
if len(temp) == 1:
self.header_bytes += temp
else:
h, b = temp
self.header_bytes += h
self.body_bytes += b
header_flag = True
@property
def header_str(self):
return str(self.header_bytes, encoding='utf-8')
def initialize_headers(self):
headers = self.header_str.split('\r\n')
first_line = headers[0].split(' ')
if len(first_line) == 3:
self.method, self.url, self.protocol = headers[0].split(' ')
for line in headers:
kv = line.split(':')
if len(kv) == 2:
k, v = kv
self.header_dict[k] = v
class Future(object):
def __init__(self):
self.result = None
F = None
def index(request):
global F
F = Future()
return F
def main(request):
return 'main'
def stop(request):
global F
F.result = b'sda'
return 'stop'
routers = [
('/index/',index),
('/main/',main),
('/stop/',stop),
]
def run():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 9999,))
sock.setblocking(False)
sock.listen(128)
inputs = []
inputs.append(sock)
async_request_dict = {}
while True:
rlist,wlist,elist = select.select(inputs,[],[],0.05)
for r in rlist:
if r == sock:
'''新请求到来'''
conn,addr = sock.accept()
conn.setblocking(False) #设置客户端socket非阻塞
inputs.append(conn)
else:
"""客户端发来数据"""
data = b"" #包含请求头、请求体
while True:
try:
chunks = r.recv(1024) #接收字节类型
data += chunks
except Exception as e:
chunks = None
if not chunks:
break
request = HttpRequest(data)
# print(request.url)
# print(request.method)
# print(request.header_dict)
# print(request.body_bytes)
# 1. 请求头获取url
# 2. 路由匹配,获取指定函数
import re
flag = False
func = None
for route in routers:
if re.match(route[0],request.url):
flag = True
func = route[1]
break
if flag:
result = func(request)
if isinstance(result,Future):
async_request_dict[r]=result #不关闭连接,加入列表
else:
r.sendall(bytes(result,encoding='utf-8'))
inputs.remove(r)
r.close()
else:
r.sendall(b'404')
inputs.remove(r)
r.close()
# 3. 执行函数,获取返回值
# 4.r.sendall(b'asd')
for conn in async_request_dict.keys():
future = async_request_dict[conn]
if future.result:
conn.sendall(future.result)
conn.close()
del async_request_dict[conn]
inputs.remove(conn)
else:
pass
if __name__ =='__main__':
run()