[TOC] >[success] # 负责启动服务器 server.py ~~~ 1. 创建一个Request,用来封装每个用户请求的 method、path、query、body headers、cookies 信息,其中form 保存post 请求从body获取的参数 2.Reuest 方法中 add_header 把获取的请求头数据进行处理封装到字典 3.add_cookies 获取封装header 中的cookies 4.run socket 启动服务装置 5.process_request 获取输入请求 6.parsed_path 处理get 请求的参数 7.response_for_path 路由映射 ~~~ ~~~ import socket import urllib.parse import _thread from routes.routes_static import route_static from routes.routes_static import route_dict from utils import log class Request: def __init__(self): self.method = "GET" self.path = '' self.query = {} self.body ='' self.headers = {} self.cookies ={} def add_cookies(self): """ 从头部获取到cookies 信息 :return: """ cookies = self.headers.get('Cookie', '') kvs = cookies.split('; ') log('cookie', kvs) for kv in kvs: if '=' in kv: k, v = kv.split("=") self.cookies[k] = v def add_header(self, header): lines = header for line in lines: k, v = line.split(': ', 1) self.headers[k] = v self.add_cookies() def form(self): f = {} args = self.body.split("&") log('form debug', args, len(args)) for arg in args: k, v = arg.split('=') f[k] = urllib.parse.unquote(v) return f def error(request, code=404): """ 根据 code 返回不同的错误响应 目前只有 404 """ e = { 404: b'HTTP/1.1 404 NOT FOUND\r\n\r\n<h1>NOT FOUND</h1>', } return e.get(code, b'') # socket 启动开始 def run(host='', port=3000): """ 启动服务器 """ # 初始化 socket 使用with 可以保证正确关闭socket 释放的占用的端口 log('start at', '{}:{}'.format(host, port)) with socket.socket() as s: s.bind((host, port)) s.listen(5) while True: connection, address = s.accept() print('连接成功, 使用多线程处理请求', address) # 开一个新的线程来处理请求, 第二个参数是传给新函数的参数列表, 必须是 tuple # tuple 如果只有一个值 必须带逗号,就是函数的参数 _thread.start_new_thread(process_request, (connection,)) def process_request(connection): r = connection.recv(1100) log('请求request', r) r = r.decode('utf-8') if len(r.split()) < 2: connection.close() log('r', r.split()) path = r.split()[1] # 进来一个连接创建一个 request 请求对象 request = Request() request.method = r.split()[0] request.add_header(r.split('\r\n\r\n', 1)[0].split('\r\n')[1:]) request.body = r.split('\r\n\r\n', 1)[1] # 用 response_for_path 函数来得到 path 对应的响应内容 response = response_for_path(path, request) # 把响应发送给客户端 connection.sendall(response) try: log(response.decode('utf-8').replace('\r\n', '\n')) except Exception as e: log('异常', e) # 处理完请求, 关闭连接 connection.close() # 用来判断 连接是get 还是 post 然后 通过链接获取参数 def parsed_path(path): index = path.find('?') if index == -1: return path,{} else: path, query_string = path.split('?', 1) args = query_string.split('&') query = {} for arg in args: k, v = arg.split('=') query[k] = v return path, query def response_for_path(path, request): path, query = parsed_path(path) request.path = path request.query = query r = { '/static': route_static, } # 注册外部的路由 r.update(route_dict) response = r.get(path, error) return response(request) if __name__ == '__main__': # 生成配置并且运行程序 config = dict( host='', port=8000, ) run(**config) ~~~